diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml index bf06ba0..482e6b4 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ b/.github/ISSUE_TEMPLATE/feature_request.yml @@ -1,5 +1,5 @@ name: Feature request -description: Propose a capability or a change in behaviour. +description: Propose a capability or a change in behavior. labels: [enhancement, needs-triage] body: - type: textarea diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index fe67aa6..b38cce0 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -6,7 +6,7 @@ Keep the title in Conventional Commits form, e.g. ## What this changes - + ## Why @@ -28,4 +28,4 @@ Keep the title in Conventional Commits form, e.g. - [ ] The `GShareSession` CRD changed — `make -C operator manifests` was re-run and the chart CRD updated - [ ] The backend API surface changed — `make gen-openapi` was re-run - [ ] User-visible strings changed — both `en` and `ko` bundles are updated -- [ ] Documentation under `docs/` reflects the new behaviour +- [ ] Documentation under `docs/` reflects the new behavior diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f36870b..a34d3cc 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -28,6 +28,19 @@ updates: open-pull-requests-limit: 5 labels: [dependencies, frontend] groups: + # These four families declare peer ranges on each other, so a package raised on its own is + # simply uninstallable: npm refuses the tree and the PR fails at the install step before a + # test ever runs. Grouping them means one PR that can actually be evaluated. + vite: + patterns: ["vite", "@vitejs/*", "vitest", "@vitest/*", "jsdom"] + i18n: + patterns: ["i18next", "i18next-*", "react-i18next"] + eslint: + patterns: ["eslint", "eslint-*", "@typescript-eslint/*"] + tailwind: + patterns: ["tailwindcss", "@tailwindcss/*", "postcss", "postcss-*", "autoprefixer"] + # Everything else, minor and patch only. A major outside the families above still arrives + # as its own PR, which is what you want for something like React. frontend-minor: update-types: [minor, patch] diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdbf981..00817c0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -97,7 +97,8 @@ jobs: - uses: actions/checkout@v7 - uses: actions/setup-node@v7 with: - node-version: "20" + # vitest 5 and jsdom 30 declare Node ^22.12 as their floor; the image builds on node:26. + node-version: "22" cache: npm cache-dependency-path: frontend/package-lock.json - name: Install diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 3360328..abb6a10 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -4,8 +4,9 @@ # the result straight to Pages, so there is no gh-pages branch to keep in sync. # # Before the first run, an administrator has to set Settings → Pages → Source to "GitHub Actions" -# on this repository. The site is then served at https://boanlab.github.io/gshare/ as a project +# on this repository. The site is then served at https://boanlab.github.io/gShare/ as a project # site, which is per-repository and does not occupy the organization's single boanlab.github.io. +# Pages paths are case-sensitive, so the base path matches the repository name exactly. name: Docs site on: @@ -30,7 +31,7 @@ concurrency: env: SITE_URL: https://boanlab.github.io - SITE_BASE_URL: /gshare/ + SITE_BASE_URL: /gShare/ jobs: build: @@ -54,15 +55,24 @@ jobs: # Nothing here needs editing to preview a fork. - name: Resolve the site address run: | - if [ "$GITHUB_REPOSITORY" != "boanlab/gshare" ]; then + if [ "$GITHUB_REPOSITORY" != "boanlab/gShare" ]; then owner="${GITHUB_REPOSITORY%%/*}" name="${GITHUB_REPOSITORY##*/}" echo "SITE_URL=https://${owner}.github.io" >> "$GITHUB_ENV" echo "SITE_BASE_URL=/${name}/" >> "$GITHUB_ENV" fi - - name: Build - run: npm run build + # One build per locale. Korean is served at the site root and English at /en, so the two + # locales write to different paths and a single combined build would have the second + # overwrite the first. The trees are merged into build/ for upload. + - name: Build both locales + run: | + rm -rf build build-ko build-en + npx docusaurus build --locale ko --out-dir build-ko + npx docusaurus build --locale en --out-dir build-en + mv build-ko build + mv build-en/en build/en + rmdir build-en - uses: actions/configure-pages@v5 diff --git a/.github/workflows/publish-session-images.yml b/.github/workflows/publish-session-images.yml index 7443812..6ffb0fb 100644 --- a/.github/workflows/publish-session-images.yml +++ b/.github/workflows/publish-session-images.yml @@ -1,6 +1,6 @@ name: Publish session images -# The session catalogue images (build/images) are large and change rarely, so they are published +# The session catalog images (build/images) are large and change rarely, so they are published # on demand and on release tags — not on every push to main. The control plane seeds # boanlab/gshare-session: references at startup (app/auth/bootstrap.py), so every tag the # seed names must exist here or a fresh install offers images that cannot be pulled. diff --git a/.gitignore b/.gitignore index a868c2e..056c6f9 100644 --- a/.gitignore +++ b/.gitignore @@ -67,11 +67,11 @@ hack/cluster-info hack/storage-csi-key hack/storage-csi-key.pub -# UX audit reports are a point-in-time artefact of a local run, not source. +# UX audit reports are a point-in-time artifact of a local run, not source. test/e2e/ux/out/ test/e2e/ux/out-*/ -# Beta-test findings and their run logs: the same kind of point-in-time artefact. +# Beta-test findings and their run logs: the same kind of point-in-time artifact. beta-report/ # ── Local assistant/agent tooling: workstation config, not project source. ── diff --git a/.trivyignore.yaml b/.trivyignore.yaml index f039b00..03e8b9b 100644 --- a/.trivyignore.yaml +++ b/.trivyignore.yaml @@ -6,8 +6,8 @@ misconfigurations: # ── Observability agents: they exist to read host and GPU state ────────────────────────── # node-exporter and dcgm-exporter are upstream DaemonSets. Host namespaces, hostPath mounts - # and SYS_ADMIN are what let them export node metrics and per-process GPU utilisation; the - # scheduler's idle reaper depends on that utilisation signal. Removing the access does not + # and SYS_ADMIN are what let them export node metrics and per-process GPU utilization; the + # scheduler's idle reaper depends on that utilization signal. Removing the access does not # harden the deployment, it disables monitoring. - id: AVD-KSV-0005 # SYS_ADMIN capability added (DCGM profiling counters) paths: diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fb99e1e..bdf8152 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,7 +52,7 @@ prerequisites are in [`test/e2e/README.md`](./test/e2e/README.md). - Commit messages and pull request titles follow [Conventional Commits](https://www.conventionalcommits.org/): `feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`, with an optional scope such as `feat(scheduler):`. -- Keep a pull request to one concern. A refactor and a behaviour change in the same diff +- Keep a pull request to one concern. A refactor and a behavior change in the same diff are two pull requests. ## Code style @@ -100,7 +100,7 @@ CI fails the build if the operator's generated files are stale. domain layer, `fakeredis` for idempotency and queue paths. - Anything that needs real compute, real VRAM isolation, or numerical accuracy is marked `realgpu` and only runs against a real GPU cluster from `test/e2e/`. -- New behaviour needs a test. Bug fixes need a test that fails before the fix. +- New behavior needs a test. Bug fixes need a test that fails before the fix. ```bash make test # everything that runs without a GPU diff --git a/README.md b/README.md index c8f6dbe..67cd3db 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ sitting on it. the card; billing stops entirely. Resuming re-acquires a card and rebuilds the pod. Volumes are kept and are not billed. - **Idle reaping.** Sessions that stop using their GPU can be paused automatically, driven - by real per-GPU utilisation from DCGM or the HAMi device-plugin monitor. + by real per-GPU utilization from DCGM or the HAMi device-plugin monitor. - **Multi-tenancy with three role planes.** Organization → group → user, with `super_admin`, `org_admin`, `group_admin`, and `member`/`guest` memberships. - **Multi-cluster.** One control plane can drive several GPU clusters, each running its own @@ -57,8 +57,8 @@ sitting on it. | `frontend/` | The console: a React + TypeScript single-page app with live updates over SSE | | `charts/gshare/` | The Helm chart for the whole platform | | `deploy/` | Values overlays (`values/`), security baselines, monitoring, supply-chain policy, secret examples | -| `build/` | Image build contexts: catalogue session images (`images/`) and the patched HAMi scheduler (`hami-fork/`) | -| `hack/` | Developer and operator scripts: cluster bootstrap, secret generation, OpenAPI generation, catalogue seeding | +| `build/` | Image build contexts: catalog session images (`images/`) and the patched HAMi scheduler (`hami-fork/`) | +| `hack/` | Developer and operator scripts: cluster bootstrap, secret generation, OpenAPI generation, catalog seeding | | `test/e2e/` | End-to-end assets: real-GPU suites, plus role and UX checks that need only the control plane | | `docs/` | User manual, administrator manual, deployment and design documentation | diff --git a/SECURITY.md b/SECURITY.md index 7353039..ad8d8dd 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -24,7 +24,7 @@ enough detail to reproduce. A proof of concept helps but is not required. What to expect: -- Acknowledgement within 5 working days. +- Acknowledgment within 5 working days. - An assessment, and a fix or mitigation plan, within 30 days for confirmed issues. - Credit in the release notes unless you ask otherwise. @@ -45,7 +45,7 @@ Out of scope: `third_party/`). - Findings that require cluster-admin on the hosting cluster, which is already a full compromise. - Denial of service caused by a tenant exhausting the credits or quota assigned to them — - that is the intended accounting behaviour. + that is the intended accounting behavior. ## Hardening expectations for operators diff --git a/backend/README.md b/backend/README.md index 24185da..9791942 100644 --- a/backend/README.md +++ b/backend/README.md @@ -2,7 +2,7 @@ The FastAPI control plane, and the authority on **money and session state**: REST, authentication and RBAC, the credit engine (hold, consume, settle, refund), budget and -FinOps gates, CRUD for the catalogue, presets, policies, users, and organizations, the +FinOps gates, CRUD for the catalog, presets, policies, users, and organizations, the audit trail, connect-token issuing, and **session admission**. It pairs with the Go cluster operator in [`../operator`](../operator), which owns diff --git a/backend/alembic/versions/0017_org_scoped_membership.py b/backend/alembic/versions/0017_org_scoped_membership.py index 7e7bcca..a6929a7 100644 --- a/backend/alembic/versions/0017_org_scoped_membership.py +++ b/backend/alembic/versions/0017_org_scoped_membership.py @@ -31,7 +31,7 @@ def upgrade() -> None: "fk_membership_org_id_organization", "membership", "organization", ["org_id"], ["id"] ) - # 2. Drop the (user_id, group_id) unique constraint in favour of two partial unique indexes. + # 2. Drop the (user_id, group_id) unique constraint in favor of two partial unique indexes. op.drop_constraint("uq_membership_user_id", "membership", type_="unique") op.create_index( "uq_membership_user_group", "membership", ["user_id", "group_id"], diff --git a/backend/alembic/versions/0021_image_public.py b/backend/alembic/versions/0021_image_public.py index 2ad19d8..4b2cb1b 100644 --- a/backend/alembic/versions/0021_image_public.py +++ b/backend/alembic/versions/0021_image_public.py @@ -1,6 +1,6 @@ """image: add a public column -Private images are hidden from the session wizard, while the administrative catalogue always shows +Private images are hidden from the session wizard, while the administrative catalog always shows them. Existing rows are marked public. Revision ID: 0021_image_public diff --git a/backend/alembic/versions/0022_rename_base_image_tags.py b/backend/alembic/versions/0022_rename_base_image_tags.py index 3c6727f..dac49cd 100644 --- a/backend/alembic/versions/0022_rename_base_image_tags.py +++ b/backend/alembic/versions/0022_rename_base_image_tags.py @@ -1,6 +1,6 @@ """base image registry tags: drop the -cpu and -gpu suffixes -Realigns the catalogue rows with the simplified build.sh tags (ml-ubuntu24.04-cpu becomes +Realigns the catalog rows with the simplified build.sh tags (ml-ubuntu24.04-cpu becomes ml-ubuntu24.04, ml-cuda12.4-cudnn9-gpu becomes ml-cuda12.4-cudnn9). Seeding deduplicates on the registry reference, so without this the next startup would create duplicate rows. diff --git a/backend/alembic/versions/0029_alloc_kind_resident_spot.py b/backend/alembic/versions/0029_alloc_kind_resident_spot.py index fbeeba5..5ba0dec 100644 --- a/backend/alembic/versions/0029_alloc_kind_resident_spot.py +++ b/backend/alembic/versions/0029_alloc_kind_resident_spot.py @@ -1,7 +1,7 @@ """allocation.kind terminology: owner becomes resident, borrow becomes spot Aligns the code identifier (Allocation.kind) with the terminology used in the design notes. Updates -both the existing rows and the server default. Behaviour is unchanged; only the role labels move. +both the existing rows and the server default. Behavior is unchanged; only the role labels move. Revision ID: 0029_alloc_kind_resident_spot Revises: 0028_webhook_org diff --git a/backend/alembic/versions/0040_image_registry_per_owner.py b/backend/alembic/versions/0040_image_registry_per_owner.py index 88ae70f..1cabaf1 100644 --- a/backend/alembic/versions/0040_image_registry_per_owner.py +++ b/backend/alembic/versions/0040_image_registry_per_owner.py @@ -3,7 +3,7 @@ Imports used to be admin-only, so one row per registry ref was enough. Members may now import a public image for themselves, which means two users can legitimately hold the same ref. Uniqueness therefore moves to (registry, owner_user_id); because Postgres considers NULL owners distinct, the -shared catalogue keeps its own partial unique index on registry alone. +shared catalog keeps its own partial unique index on registry alone. Any older single-column UNIQUE on image.registry is dropped first (constraint or index — earlier deployments differ), so this migration is safe on a database that never had one. diff --git a/backend/app/api/credits_router.py b/backend/app/api/credits_router.py index ecab97b..38956e9 100644 --- a/backend/app/api/credits_router.py +++ b/backend/app/api/credits_router.py @@ -1232,7 +1232,7 @@ async def reject_allocation_request( # ── ledger reads ─────────────────────────────────────────────── async def _resolve_ref_names(db: AsyncSession, refs: set[str]) -> dict[str, str]: - """Map a transaction ref to something a person recognises: the session's name, or a label.""" + """Map a transaction ref to something a person recognizes: the session's name, or a label.""" out: dict[str, str] = {} ses_ids = {r for r in refs if r.startswith("ses_")} if ses_ids: diff --git a/backend/app/api/groups_router.py b/backend/app/api/groups_router.py index fd9bf9d..0531334 100644 --- a/backend/app/api/groups_router.py +++ b/backend/app/api/groups_router.py @@ -655,7 +655,7 @@ async def create_project( async def _cascade_group_users( db: AsyncSession, group_ids: list[str], to_status: str, actor: str, ) -> int: - """Deactivate/reactivate the users of the given groups, honouring multi-membership. + """Deactivate/reactivate the users of the given groups, honoring multi-membership. Deactivate: only users whose EVERY OTHER group membership is in an inactive/archived or deleted group go inactive — someone also in an active department keeps working. diff --git a/backend/app/api/images_router.py b/backend/app/api/images_router.py index d864e74..e30287d 100644 --- a/backend/app/api/images_router.py +++ b/backend/app/api/images_router.py @@ -61,7 +61,7 @@ class _Validation(DomainError): class _ImageLimit(DomainError): # A member may own only MAX_USER_IMAGES images; the cap keeps one user from filling the - # catalogue (and the build registry) on their own. + # catalog (and the build registry) on their own. code, http = "image_limit_reached", 409 @@ -126,7 +126,7 @@ def _serialize_image(img: Image) -> dict[str, Any]: # GPUs. "cuda_version": (img.tags or {}).get("cuda_version"), "gpu_ready": bool((img.tags or {}).get("gpu_ready", False)), - # A private image is hidden from the session wizard, though the admin catalogue always lists + # A private image is hidden from the session wizard, though the admin catalog always lists # it. "public": getattr(img, "public", True), "owner_user_id": img.owner_user_id, @@ -168,11 +168,11 @@ async def list_images( """List images/templates/ISOs with optional kind/q/tag/public filters. any authenticated. ``public=true`` is what the session wizard uses, listing public images only. The administrative - catalogue passes no filter and sees both public and private images. + catalog passes no filter and sees both public and private images. """ base = select(Image) - # Only the catalogue administrators (image.create) see every row. Everyone else is limited to - # the shared catalogue plus their own private images, whatever filter they pass — a private + # Only the catalog administrators (image.create) see every row. Everyone else is limited to + # the shared catalog plus their own private images, whatever filter they pass — a private # image built by another user (its registry path included) is not theirs to list. if not rbac_allows(principal, "image.create"): base = base.where(or_(Image.public.is_(True), Image.owner_user_id == principal.user_id)) @@ -276,7 +276,7 @@ async def get_image( principal: Principal = Depends(get_current_principal), db: AsyncSession = Depends(get_db), ): - """Image detail. any authenticated, for the shared catalogue and one's own images; another + """Image detail. any authenticated, for the shared catalog and one's own images; another user's private image answers 404 so its existence is not confirmed either.""" img = await db.get(Image, image_id) if img is None: @@ -359,7 +359,7 @@ async def delete_image( principal: Principal = Depends(get_current_principal), db: AsyncSession = Depends(get_db), ): - """Delete a catalogue image that no session has ever used. super_admin, gated on image.create. + """Delete a catalog image that no session has ever used. super_admin, gated on image.create. Sessions keep a foreign key to their image for the audit trail, so an image with any session history cannot be deleted — retire it instead by setting ``public: false``. @@ -452,7 +452,7 @@ async def import_image( only they and admins can see. The same public ref may therefore be imported by many members. Always answers 202. Deduplication never fails the request: re-importing your own ref, or a ref - that is already in the shared catalogue, returns that row with ``existing: true`` instead of + that is already in the shared catalog, returns that row with ``existing: true`` instead of creating a second one — the caller uses the returned ``id`` either way. """ if getattr(body, "registry_auth", None): @@ -477,7 +477,7 @@ async def import_image( raise _Conflict("registry already registered", {"registry": ref}) else: # Users may not bring their own images any more: everything a session can run comes - # from the administrator-curated catalogue (build or import on the admin side). A + # from the administrator-curated catalog (build or import on the admin side). A # member import used to mint a private row here; that path is closed for security. raise Forbidden("importing images is restricted to administrators") diff --git a/backend/app/api/infra_router.py b/backend/app/api/infra_router.py index dfc4423..226ed6b 100644 --- a/backend/app/api/infra_router.py +++ b/backend/app/api/infra_router.py @@ -139,7 +139,7 @@ async def _node_allocations(db: AsyncSession, node_ids: list[str]) -> dict[str, def _node_out( n: GpuNode, devices: list[GpuDevice] | None = None, pool_name: str | None = None ) -> dict: - """Serialise a node in the same shape as a list item; shared by the cordon, drain, register and + """Serialize a node in the same shape as a list item; shared by the cordon, drain, register and set-pool responses.""" nd = devices or [] gpu_mode, mode_counts = _mode_summary(nd) @@ -341,7 +341,7 @@ async def register_node( hostname=body.hostname, cluster_id=cluster_id, ) await db.commit() - await db.refresh(node) # pick up server defaults such as updated_at before serialising, avoiding MissingGreenlet + await db.refresh(node) # pick up server defaults such as updated_at before serializing, avoiding MissingGreenlet return _node_out(node, []) @@ -472,7 +472,7 @@ async def cordon_node( cordon=body.cordon, reason=body.reason, ) await db.commit() - # updated_at (onupdate=now) is expired by the flush, so refresh before serialising; a + # updated_at (onupdate=now) is expired by the flush, so refresh before serializing; a # synchronous lazy load here would raise MissingGreenlet. await db.refresh(node) return _node_out(node, devs) @@ -589,7 +589,7 @@ async def drain_node( # ── Node pools ────────────────────────────────────────────────────────────────────────────────── -# Dedicated nodes per organization / group, honoured by placement (app.domain.node_pools). Pools and +# Dedicated nodes per organization / group, honored by placement (app.domain.node_pools). Pools and # node assignment are super_admin only; an org_admin sees the pools granted to their organization # and may sub-assign them to groups in that organization. CPU-only sessions and lending idle # dedicated cards to the shared pool are out of scope here. @@ -627,7 +627,7 @@ async def _group_orgs(db: AsyncSession, group_ids: set[str]) -> dict[str, str]: async def _pool_reads(db: AsyncSession, pools: list[NodePool]) -> list[dict]: - """Serialise pools with their nodes and grants (batched: one query per relation).""" + """Serialize pools with their nodes and grants (batched: one query per relation).""" if not pools: return [] pool_ids = [p.id for p in pools] @@ -1400,8 +1400,8 @@ async def metrics_cluster( } if (pools or bound_gb) else None # ALLOCATION based, deliberately: this dashboard answers "how much of the fleet is handed out", - # the same basis as vram_load_pct beside it. Measured utilisation (DCGM) is a different question - # — an allocated card can sit at 0% — and lives on the monitoring page, where it is labelled as + # the same basis as vram_load_pct beside it. Measured utilization (DCGM) is a different question + # — an allocated card can sit at 0% — and lives on the monitoring page, where it is labeled as # measured. Mixing the two bases in one row made 17% flip to 0% with no visible cause. avg_util = round(cores_used / cores_total * 100, 1) if cores_total else 0.0 @@ -1445,7 +1445,7 @@ async def metrics_cluster( def _money(v: Decimal) -> str: - """Serialise as a money-style string, rounded to two decimal places.""" + """Serialize as a money-style string, rounded to two decimal places.""" return str(Decimal(v).quantize(_TWO_DP, rounding=ROUND_HALF_UP)) @@ -1598,7 +1598,7 @@ def _wallet_key(w: CreditWallet) -> str: ).all(): name_by[oid] = oname elif group_by == "wallet": - # A wallet key is labelled "owner_type · owner_id"; the name comes from the owner lookup. + # A wallet key is labeled "owner_type · owner_id"; the name comes from the owner lookup. oids = {ow[1] for ow in wallet_owner.values()} # The wallet key here is wallet.id, so enrich it with the owner label. u = {i: n for i, n in (await db.execute(select(User.id, User.name).where(User.id.in_(oids)))).all()} if oids else {} diff --git a/backend/app/api/monitoring_router.py b/backend/app/api/monitoring_router.py index 09aec0d..de1aa8c 100644 --- a/backend/app/api/monitoring_router.py +++ b/backend/app/api/monitoring_router.py @@ -3,13 +3,13 @@ The console never talks to Prometheus directly. It names a PANEL; this router owns the PromQL. Two reasons, both load-bearing: -* Authorisation. Prometheus has no notion of GShare tenancy, so an arbitrary-PromQL passthrough - would be an authorisation hole. Every request here goes through ``monitoring.read`` +* Authorization. Prometheus has no notion of GShare tenancy, so an arbitrary-PromQL passthrough + would be an authorization hole. Every request here goes through ``monitoring.read`` (super_admin only today). * Stability. The panel ids are the contract with the console; the queries behind them can be retuned (or swapped from DCGM to HAMi) without touching the frontend. -Measured utilisation lives HERE and is labelled as measured. The admin dashboard's GPU figure is +Measured utilization lives HERE and is labeled as measured. The admin dashboard's GPU figure is deliberately allocation-based — a card can be fully allocated and sit at 0% — and the two must not be confused (see infra_router._cluster_metrics). """ @@ -188,7 +188,7 @@ def _session_pod_selector(session_id: str) -> str: async def session_usage_payload(session_id: str) -> dict[str, float | None]: - """Instant measured usage of one session's pod. The caller owns authorisation.""" + """Instant measured usage of one session's pod. The caller owns authorization.""" sel = _session_pod_selector(session_id) queries = { # irate = the last two samples: with a 5 s scrape the readout follows a load change within @@ -223,7 +223,7 @@ async def session_usage_series( session_id: str, range_: str, *, window: tuple[int, int] | None = None, ) -> dict[str, Any]: """The four usage metrics over a range, or over ``window`` (a finished session's whole run). - The caller owns authorisation.""" + The caller owns authorization.""" if window is None and range_ not in _RANGES: raise _BadPanel("unknown range", {"range": range_}) sel = _session_pod_selector(session_id) diff --git a/backend/app/api/offerings_router.py b/backend/app/api/offerings_router.py index 72318e7..b86dae6 100644 --- a/backend/app/api/offerings_router.py +++ b/backend/app/api/offerings_router.py @@ -76,7 +76,7 @@ def _offering_view(o: Offering) -> dict: def _normalize_cuda(raw: str | None) -> str | None: - """Normalise a min_cuda input: an empty string clears it, a malformed one is 422.""" + """Normalize a min_cuda input: an empty string clears it, a malformed one is 422.""" if raw is None: return None raw = raw.strip() diff --git a/backend/app/api/policies_router.py b/backend/app/api/policies_router.py index 21d73e8..0d08414 100644 --- a/backend/app/api/policies_router.py +++ b/backend/app/api/policies_router.py @@ -215,7 +215,7 @@ async def effective_policy( "max_concurrent": pol.max_concurrent, "max_queued": pol.max_queued, # Runtime/idle windows belong here too: this card is the ONLY place a user can learn - # when their session will be reaped. 0 = unlimited (same semantics the reaper honours). + # when their session will be reaped. 0 = unlimited (same semantics the reaper honors). "max_runtime_min": pol.max_runtime, "idle_timeout_sec": pol.idle_timeout, "limits": limits, @@ -496,7 +496,7 @@ async def _propagate_reaper_policy(db: AsyncSession, scope: str, scope_id: str) """Re-stamp idle/max-runtime on every ACTIVE session the (scope, scope_id) policy touches. Without this a policy edit reached live sessions only on their next resume; the reaper kept - honouring the creation-time window. Best-effort per session — a cluster hiccup must not fail + honoring the creation-time window. Best-effort per session — a cluster hiccup must not fail the policy write itself (it already committed).""" from app.cluster.crd import GShareSessionCRD from app.db.models import Membership as _M diff --git a/backend/app/api/queue_router.py b/backend/app/api/queue_router.py index 5fcf58f..f77903d 100644 --- a/backend/app/api/queue_router.py +++ b/backend/app/api/queue_router.py @@ -177,7 +177,7 @@ async def my_queue( ).all() owners = {sid: oid for sid, oid in owner_rows} # Rough wait estimate from the median of the last realized queue waits: position × median. - # Deliberately labelled an estimate in the UI; None until enough samples exist. + # Deliberately labeled an estimate in the UI; None until enough samples exist. median_wait_sec: float | None = None try: samples = [float(x) for x in await get_redis().lrange("gshare:queue:wait_samples", 0, 99)] diff --git a/backend/app/api/schemas/credit.py b/backend/app/api/schemas/credit.py index a787de4..1446204 100644 --- a/backend/app/api/schemas/credit.py +++ b/backend/app/api/schemas/credit.py @@ -134,11 +134,11 @@ class TopupRejectBody(BaseModel): class TopupRequestRead(BaseModel): - # Mirrors the serialised shape of GET /credits/topup-requests, which is assembled as a dict + # Mirrors the serialized shape of GET /credits/topup-requests, which is assembled as a dict # rather than mapped from the ORM. id: str wallet_id: str - amount: str # serialised as a string, from Decimal + amount: str # serialized as a string, from Decimal status: str requester_id: str | None = None requester_name: str | None = None diff --git a/backend/app/api/schemas/image.py b/backend/app/api/schemas/image.py index b19c803..15eae5b 100644 --- a/backend/app/api/schemas/image.py +++ b/backend/app/api/schemas/image.py @@ -27,7 +27,7 @@ class ImageRead(BaseModel): # to offer a bare OS for a GPU session. gpu_ready: bool = False public: bool = True - # null = shared catalogue entry; set = a private image its owner (and admins) can see. The + # null = shared catalog entry; set = a private image its owner (and admins) can see. The # console distinguishes the caller's own images with it, so it has to survive the projection. owner_user_id: str | None = None created_at: datetime | None = None diff --git a/backend/app/api/schemas/internal.py b/backend/app/api/schemas/internal.py index 3d84aa3..d16d980 100644 --- a/backend/app/api/schemas/internal.py +++ b/backend/app/api/schemas/internal.py @@ -61,7 +61,7 @@ class OperatorNodeUpsert(BaseModel): node_ready: bool | None = None # see OperatorGpuDeviceUpsert.node_ready node_mem_gb: int | None = None node_disk_gb: int | None = None - lossless_capable: bool = False # lossless-pause prerequisites (cuda-checkpoint plus CRIU) are labelled ready on the node + lossless_capable: bool = False # lossless-pause prerequisites (cuda-checkpoint plus CRIU) are labeled ready on the node role: str | None = None # master|gpu|cpu|storage, from node labels/devices diff --git a/backend/app/api/schemas/session.py b/backend/app/api/schemas/session.py index c78421a..a79d947 100644 --- a/backend/app/api/schemas/session.py +++ b/backend/app/api/schemas/session.py @@ -124,7 +124,7 @@ class SessionRead(ORMModel): gpu_model: str | None = None # The bound card's operator-given alias ("lab-A-01"), when one is set. gpu_alias: str | None = None - # WHICH image the session runs: the catalogue name a person recognises, and the registry + # WHICH image the session runs: the catalog name a person recognizes, and the registry # reference behind it. Without these the only clue was the image id, so nobody could tell # what a running session was actually built from. image_name: str | None = None diff --git a/backend/app/api/users_router.py b/backend/app/api/users_router.py index adbecf7..0857270 100644 --- a/backend/app/api/users_router.py +++ b/backend/app/api/users_router.py @@ -1276,7 +1276,7 @@ async def delete_user( svc = SessionService(db) for sid in live_ids: - # terminate() commits internally (it serialises on the session row); idempotent. + # terminate() commits internally (it serializes on the session row); idempotent. await svc.terminate(sid, forced=True, reason="admin_stopped") # terminate()'s commits expired the identity map; re-fetch the row we mutate below. user = await db.get(User, user_id) @@ -1345,7 +1345,7 @@ async def set_global_role( requested = [body.global_role] else: requested = [] - # Normalise: deduplicate and validate. + # Normalize: deduplicate and validate. roles: list[str] = [] for r in requested: if r not in _GLOBAL_ROLES: diff --git a/backend/app/auth/bootstrap.py b/backend/app/auth/bootstrap.py index 2fc43f4..b51f6d8 100644 --- a/backend/app/auth/bootstrap.py +++ b/backend/app/auth/bootstrap.py @@ -29,7 +29,7 @@ log = get_logger(__name__) -# The catalogue images: session bases published to Docker Hub under boanlab, registered +# The catalog images: session bases published to Docker Hub under boanlab, registered # idempotently at startup. cuda_version is the real CUDA baked into the registry tag, which the # session wizard compares against the offering's min_cuda. # @@ -54,7 +54,7 @@ {"name": "TensorFlow NGC 25.02 (GPU, CUDA 12.8)", "registry": "boanlab/gshare-session:tensorflow-ngc25.02-cuda12.8", "cuda_version": "12.8"}, ] -# The default GPU offering catalogue: one full-card row per model. The session wizard derives the +# The default GPU offering catalog: one full-card row per model. The session wizard derives the # per-model fraction tiers from the full-card VRAM. # # Host cpu/mem/disk are IDENTICAL across models by policy (host resources are GPU-agnostic; @@ -105,7 +105,7 @@ ] # Preset names superseded by the split compute/gpu presets, removed on every re-seed. This also # covers GPU presets renamed when the ladder was remapped to XL-L-M-S-SS, and the original -# Korean-named presets replaced when the catalogue moved to English. +# Korean-named presets replaced when the catalog moved to English. _LEGACY_PRESET_NAMES = [ "Small (1/4)", "Medium (1/2)", "Large (full)", "XLarge (48G)", "GPU S (1/8)", "GPU M (1/4)", "GPU L (1/2)", "GPU SS (1/16)", "GPU SSS (1/32)", @@ -176,7 +176,7 @@ async def seed_default_policy() -> None: async def seed_offerings() -> None: - """Ensure the default GPU offering catalogue exists, skipping duplicates by name. + """Ensure the default GPU offering catalog exists, skipping duplicates by name. One full-card row per model; the wizard derives the fraction tiers. If your fleet reports GPU model names that differ from these, adjust gpu_model or nothing will schedule against them. @@ -253,7 +253,7 @@ async def seed_system_wallet() -> None: async def seed_base_images() -> None: - """Ensure the four catalogue images exist, skipping duplicates by registry reference. + """Ensure the four catalog images exist, skipping duplicates by registry reference. This is what lets users and administrators pick an image on the images screen without importing anything first. They are registered with import_status=ready, since the base images already @@ -277,7 +277,7 @@ async def seed_base_images() -> None: if spec.get("gpu_ready") and not (existing.tags or {}).get("gpu_ready"): existing.tags = {**(existing.tags or {}), "gpu_ready": True} log.info("base image marked gpu_ready: %s", spec["registry"]) - # The catalogue name is the seed's to own; "(CPU)" was wrong once these + # The catalog name is the seed's to own; "(CPU)" was wrong once these # images became valid GPU choices too. if existing.name != spec["name"]: log.info("base image renamed: %r -> %r", existing.name, spec["name"]) diff --git a/backend/app/auth/rbac.py b/backend/app/auth/rbac.py index a9b4d22..b6205f6 100644 --- a/backend/app/auth/rbac.py +++ b/backend/app/auth/rbac.py @@ -80,7 +80,7 @@ def primary_global_role(roles: list[str] | set[str] | None) -> str | None: "policy.delete": ("super_admin", ("scoped", "group_admin")), # Monitoring — raw fleet telemetry (measured GPU/host metrics) is system-admin only. "monitoring.read": ("super_admin",), - # Images — catalogue management is super_admin only; building is project work, member and above + # Images — catalog management is super_admin only; building is project work, member and above "image.create": ("super_admin",), "image.build": ("super_admin", ("scoped", "member")), # Sessions — create/read member+, force-terminate group_admin+, monitor group_admin+ diff --git a/backend/app/cluster/inventory_sync.py b/backend/app/cluster/inventory_sync.py index cc05c9a..41b7121 100644 --- a/backend/app/cluster/inventory_sync.py +++ b/backend/app/cluster/inventory_sync.py @@ -195,9 +195,9 @@ async def upsert_device(self, ev: OperatorGpuDeviceUpsert, cluster_id: str) -> N async def align_offering_models(db: AsyncSession, reported: str) -> None: - """Make the catalogue speak the fleet's exact model string. + """Make the catalog speak the fleet's exact model string. - Admission matches ``offering.gpu_model == device.model`` verbatim. The seeded catalogue carries + Admission matches ``offering.gpu_model == device.model`` verbatim. The seeded catalog carries the marketing name ("NVIDIA RTX PRO 6000 Blackwell"); the driver reports the full SKU ("NVIDIA RTX PRO 6000 Blackwell Max-Q Workstation Edition"). Until an administrator noticed and retyped it, every session on such a fleet answered ``409 unserviceable``. When a device diff --git a/backend/app/cluster/status_sync.py b/backend/app/cluster/status_sync.py index 9c37a4a..8c8c579 100644 --- a/backend/app/cluster/status_sync.py +++ b/backend/app/cluster/status_sync.py @@ -133,7 +133,7 @@ async def on_status(self, session_id: str, ev: OperatorStatusEvent) -> None: # reason-less Paused right after a resume is the echo of the backend stop that # resume overtook. Reading it as an idle pause released the new reservation and # left the session "paused" while its pod ran for free. Older operators that send - # no reason are still honoured outside this window. + # no reason are still honored outside this window. log.info("paused echo without a reason for freshly resumed session %s ignored", sess.id) return if phase == "paused" and sess.status == "paused": @@ -567,7 +567,7 @@ async def _load_session(self, session_id: str) -> Session | None: if sess is None: # The operator addresses the custom resource by its RFC 1123 name (lower-cased with `_` # replaced by `-`; see crd._cr_name), which does not equal the original session id - # (ses_), so the same normalisation is applied to match back. + # (ses_), so the same normalization is applied to match back. sess = ( await self.db.execute( select(Session).where( diff --git a/backend/app/core/config.py b/backend/app/core/config.py index 4df455b..4642b01 100644 --- a/backend/app/core/config.py +++ b/backend/app/core/config.py @@ -113,7 +113,7 @@ class Settings(BaseSettings): # Placement policy for fractional slices: binpack (tightest two-dimensional fit, consolidating # onto cards and keeping empty ones free) or spread (balance the load). GPU_PACKING: str = "binpack" - PROMETHEUS_URL: str = "http://prometheus.monitoring.svc:9090" # source of aggregated DCGM utilisation + PROMETHEUS_URL: str = "http://prometheus.monitoring.svc:9090" # source of aggregated DCGM utilization # ── Host admission headroom ── # Host headroom kept out of admission on every node, covering the kubelet/system reserve and # daemonset pods, so a session admitted against inventory capacity still schedules. A card only @@ -124,9 +124,9 @@ class Settings(BaseSettings): NODE_STALE_SEC: int = 300 # Capacity of the volume backing pool (GB) for the admin dashboard's storage panel. The # operator only sees a node's root disk, which is not the ZFS pool the volumes live on; 0 = - # unknown, and the panel then shows the storage nodes' disk, labelled as such. + # unknown, and the panel then shows the storage nodes' disk, labeled as such. STORAGE_POOL_CAPACITY_GB: int = 0 - # Seed the boanlab/gshare-session catalogue images at startup. A site that serves session + # Seed the boanlab/gshare-session catalog images at startup. A site that serves session # images from its own registry registers them by hand and turns this off, or the Docker Hub # references would sit next to the local ones and fail to pull. SEED_SESSION_IMAGES: bool = True diff --git a/backend/app/db/models.py b/backend/app/db/models.py index 9816c7b..6a95138 100644 --- a/backend/app/db/models.py +++ b/backend/app/db/models.py @@ -286,7 +286,7 @@ class Image(Base, TimestampMixin): # null owner = shared catalog entry; set = a user-built private image (owner + admins only) owner_user_id: Mapped[str | None] = mapped_column(String, index=True, default=None) # The same public ref may be imported by many members, so uniqueness is per owner. Postgres - # treats NULL owners as distinct rows, so shared catalogue refs need the second, partial index + # treats NULL owners as distinct rows, so shared catalog refs need the second, partial index # to stay unique among themselves. __table_args__ = ( Index("uq_image_registry_owner", "registry", "owner_user_id", unique=True), @@ -373,7 +373,7 @@ class GpuNode(Base, TimestampMixin): disk: Mapped[int | None] = mapped_column(Integer, default=None) # node ephemeral storage in GiB role: Mapped[str | None] = mapped_column(String, default=None) # master|gpu|cpu|storage (operator-derived) region: Mapped[str | None] = mapped_column(String, default=None) - # Whether the lossless-pause prerequisites (cuda-checkpoint plus CRIU) are labelled ready on the + # Whether the lossless-pause prerequisites (cuda-checkpoint plus CRIU) are labeled ready on the # node; reported by the operator's inventory controller. lossless_capable: Mapped[bool] = mapped_column(Boolean, default=False, server_default=text("false")) # Node pool membership. NULL behaves as "shared": usable by every tenant. See NodePool. @@ -410,7 +410,7 @@ class StoragePool(Base, TimestampMixin, SoftDeleteMixin): Capacity is measured, not typed in: the operator reads the CSI driver's own answer (CSIStorageCapacity, published by the external-provisioner) and reports it here. A site whose driver does not publish capacity falls back to `manual_capacity_gb`, and failing that to the - storage node's root disk — which is not the pool and is labelled as such. + storage node's root disk — which is not the pool and is labeled as such. """ __tablename__ = "storage_pool" id: Mapped[str] = mapped_column(String, primary_key=True) # stp_ULID diff --git a/backend/app/domain/policy.py b/backend/app/domain/policy.py index b93ce11..bb687f6 100644 --- a/backend/app/domain/policy.py +++ b/backend/app/domain/policy.py @@ -3,7 +3,7 @@ Policies live at four scopes (user > group > org > global). Resolution is **per-field** most-specific-wins: each field comes from the most specific policy that sets it, so a user-scoped policy that only lowers ``max_concurrent`` no longer silently discards the group's runtime and -idle limits (the old first-matching-ROW-wins behaviour, which was also implemented three times in +idle limits (the old first-matching-ROW-wins behavior, which was also implemented three times in three modules). ``limits`` merges per key the same way. Consumers: the scheduler admission gate, the ``/resource-policies/effective`` endpoint, and the diff --git a/backend/app/domain/scheduler.py b/backend/app/domain/scheduler.py index 6cdc687..2706356 100644 --- a/backend/app/domain/scheduler.py +++ b/backend/app/domain/scheduler.py @@ -392,7 +392,7 @@ def _validate_balance(self, req: SessionCreate, ref_mem: int) -> None: return mem_mb = req.gpu_mem_mb or 0 # Minimum VRAM floor: a slice below 1 GB cannot even hold a CUDA context. The frontend - # disables such tiers; this is defence in depth against direct API calls. (Exclusive has + # disables such tiers; this is defense in depth against direct API calls. (Exclusive has # already returned above.) if mem_mb < settings.GPU_MIN_FRACTIONAL_MEM_MB: raise VramBelowMinimum( @@ -1294,7 +1294,7 @@ def _reserve_target(devs, req_mem: int, req_cores: int, exclusive: bool, spread: def _mig_rounded(dev, req_mem: int, req_cores: int): """Round a request UP to the card's smallest fitting MIG instance, or None. - Profiles are modelled as the 1/4, 1/2, and full fractions of the card (RTX PRO 6000 + Profiles are modeled as the 1/4, 1/2, and full fractions of the card (RTX PRO 6000 Blackwell: 1g.24gb / 2g.48gb / 4g.96gb; A100/H100 quarters land on the same fractions closely enough for capacity accounting — HAMi's knownMigGeometries does the real carving). """ @@ -1355,9 +1355,9 @@ def _pick_device(devs, req_mem: int, req_cores: int, spread: bool | None = None) """Occupancy-aware 2D best-fit (VRAM + cores) for a fractional slice. Candidates are cards that fit in both dimensions. The score is the headroom left after - placement, as (dominant dimension, total). binpack, the default, minimises it: work + placement, as (dominant dimension, total). binpack, the default, minimizes it: work consolidates onto the fullest card, empty cards stay available for exclusive or large jobs, - and both fragmentation and dominant-resource skew stay low. spread maximises it, picking the + and both fragmentation and dominant-resource skew stay low. spread maximizes it, picking the emptiest card to balance load and reduce interference. """ candidates = [ diff --git a/backend/app/domain/session_service.py b/backend/app/domain/session_service.py index 10c41d7..b895876 100644 --- a/backend/app/domain/session_service.py +++ b/backend/app/domain/session_service.py @@ -370,7 +370,7 @@ async def terminate(self, session_id: str, *, forced: bool = False, reason: str the hold (reserved) and refunds the unconsumed balance. GPU capacity is reclaimed. """ now = _now() - # Serialise concurrent terminations: lock the session row FOR UPDATE and commit the + # Serialize concurrent terminations: lock the session row FOR UPDATE and commit the # `terminating` claim atomically. sess = await self.db.get(Session, session_id, with_for_update=True) if sess is None or sess.deleted_at is not None: diff --git a/backend/app/internal/imagebuild_status_router.py b/backend/app/internal/imagebuild_status_router.py index 7b065eb..aa5d69e 100644 --- a/backend/app/internal/imagebuild_status_router.py +++ b/backend/app/internal/imagebuild_status_router.py @@ -43,7 +43,7 @@ async def report_build_status( if build is None or ev.phase not in _PHASES: return {"accepted": False} # Only the operator of the cluster running the kaniko Job may finish this build: a - # neighbouring cluster's token could otherwise mark it succeeded with an image ref of its + # neighboring cluster's token could otherwise mark it succeeded with an image ref of its # choosing, which becomes a private Image row the owner then runs sessions from. require_operator_cluster(claims, build.cluster_id, what="image build") if build.status in _TERMINAL: # terminal never regresses (retried callbacks) diff --git a/backend/app/internal/inventory_router.py b/backend/app/internal/inventory_router.py index 0cbffe2..18a9fcf 100644 --- a/backend/app/internal/inventory_router.py +++ b/backend/app/internal/inventory_router.py @@ -35,7 +35,7 @@ async def upsert_gpu_device( db: AsyncSession = Depends(get_db), ): # The token says which cluster is reporting; a payload that names another one is refused - # rather than believed, so no attached cluster can rewrite a neighbour's inventory. + # rather than believed, so no attached cluster can rewrite a neighbor's inventory. require_operator_cluster(claims, ev.cluster_id, what="inventory report") cluster_id = operator_cluster(claims) or ev.cluster_id or str(claims.get("sub", "")) await InventorySync(db).upsert_device(ev, cluster_id) @@ -49,7 +49,7 @@ async def upsert_node( db: AsyncSession = Depends(get_db), ): # The token says which cluster is reporting; a payload that names another one is refused - # rather than believed, so no attached cluster can rewrite a neighbour's inventory. + # rather than believed, so no attached cluster can rewrite a neighbor's inventory. require_operator_cluster(claims, ev.cluster_id, what="inventory report") cluster_id = operator_cluster(claims) or ev.cluster_id or str(claims.get("sub", "")) await InventorySync(db).upsert_node(ev, cluster_id) diff --git a/backend/app/internal/volumes_router.py b/backend/app/internal/volumes_router.py index 4856fb0..0e54b1a 100644 --- a/backend/app/internal/volumes_router.py +++ b/backend/app/internal/volumes_router.py @@ -24,7 +24,7 @@ async def sync_volumes( db: AsyncSession = Depends(get_db), ) -> VolumeSyncResponse: # The report's cluster pins volume placement and pool capacity, so it has to be the token's - # cluster: no attached cluster may claim a neighbour's PVCs or rewrite its pool figures. An + # cluster: no attached cluster may claim a neighbor's PVCs or rewrite its pool figures. An # older operator that sends no cluster lands on the token's. require_operator_cluster(claims, report.cluster_id, what="volume report") if report.cluster_id is None: diff --git a/backend/app/main.py b/backend/app/main.py index 76c10cc..6e5abb8 100644 --- a/backend/app/main.py +++ b/backend/app/main.py @@ -20,7 +20,7 @@ async def _lifespan(app: FastAPI): # noqa: ANN202 # Validate the required secrets; an empty one fails fast. from app.core.config import settings settings.require_runtime_secrets() - # Bootstrap seeding: the administrator account, the all-in-one local cluster, and the catalogue. + # Bootstrap seeding: the administrator account, the all-in-one local cluster, and the catalog. # A failure here is logged but must not stop the application from starting. try: from app.auth.bootstrap import ( diff --git a/backend/pyproject.toml b/backend/pyproject.toml index 63b9c84..7e48508 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -51,7 +51,7 @@ ignore = [ "B008", # FastAPI Depends() in a default argument is idiomatic # Line length is a formatting convention here, not a gate. `line-length` above still drives # `ruff format`, and prose (comments and docstrings) is kept within it, but a fair amount of - # existing code — notably the tabular catalogue seed data — deliberately runs wider. + # existing code — notably the tabular catalog seed data — deliberately runs wider. "E501", ] diff --git a/backend/tests/conftest.py b/backend/tests/conftest.py index 6398afa..8dc0f8f 100644 --- a/backend/tests/conftest.py +++ b/backend/tests/conftest.py @@ -38,7 +38,7 @@ # ``GSHARE_TEST_DATABASE_URL`` to an asyncpg URL and the ``db`` fixture binds to that database # instead: the schema is created ONCE per session with ``alembic upgrade head`` (the production # path, not create_all) and every table is truncated after each test. Unset, nothing below -# changes the SQLite behaviour. +# changes the SQLite behavior. PG_TEST_URL = os.environ.get("GSHARE_TEST_DATABASE_URL") diff --git a/backend/tests/test_beta_lead_hypotheses.py b/backend/tests/test_beta_lead_hypotheses.py index f15831e..8403323 100644 --- a/backend/tests/test_beta_lead_hypotheses.py +++ b/backend/tests/test_beta_lead_hypotheses.py @@ -1,6 +1,6 @@ """Regression tests for the pre-review hypotheses H-1..H-6 (beta-test pass). -Each test pins one behaviour the review suspected was wrong; every one of them failed on the +Each test pins one behavior the review suspected was wrong; every one of them failed on the code as found and passes with the fix, so a later change that reopens the hole is caught here. """ from __future__ import annotations diff --git a/backend/tests/test_image_import.py b/backend/tests/test_image_import.py index 207846a..fd65ac9 100644 --- a/backend/tests/test_image_import.py +++ b/backend/tests/test_image_import.py @@ -1,8 +1,8 @@ -"""Image imports are an administrator's tool: the catalogue is curated, not user-supplied. +"""Image imports are an administrator's tool: the catalog is curated, not user-supplied. Members used to be able to register a public registry reference as a private image of their own; that path is closed for security — everything a session can run comes from the admin-curated -catalogue. These tests pin the new contract: members are refused outright, admin imports stay +catalog. These tests pin the new contract: members are refused outright, admin imports stay shared, deduplicated, and validated. """ from __future__ import annotations diff --git a/backend/tests/test_internal_cluster_binding.py b/backend/tests/test_internal_cluster_binding.py index 1cd339b..00ac081 100644 --- a/backend/tests/test_internal_cluster_binding.py +++ b/backend/tests/test_internal_cluster_binding.py @@ -2,7 +2,7 @@ Every attached cluster holds a token signed by the same control-plane key. Before this, the callbacks checked the audience and nothing else, so the operator of one cluster could report a -session on another cluster as terminated (settling its hold), rewrite a neighbour's node and card +session on another cluster as terminated (settling its hold), rewrite a neighbor's node and card inventory, or feed the live-usage view of sessions it never ran. """ from __future__ import annotations diff --git a/backend/tests/test_mixed_fleet.py b/backend/tests/test_mixed_fleet.py index ced7a05..d2712ba 100644 --- a/backend/tests/test_mixed_fleet.py +++ b/backend/tests/test_mixed_fleet.py @@ -1,7 +1,7 @@ """Mixed-fleet placement: a session priced for one GPU model never lands on another model. The fleet plan runs RTX 4090, RTX PRO 5000, and RTX PRO 6000 side by side; the reservation must -honour the offering's gpu_model even when a bigger card of another model has free capacity. +honor the offering's gpu_model even when a bigger card of another model has free capacity. """ from __future__ import annotations diff --git a/backend/tests/test_node_pools.py b/backend/tests/test_node_pools.py index cbf20e2..7727d7f 100644 --- a/backend/tests/test_node_pools.py +++ b/backend/tests/test_node_pools.py @@ -1,4 +1,4 @@ -"""Node pools: dedicated nodes per organization / group, honoured by placement. +"""Node pools: dedicated nodes per organization / group, honored by placement. Fleet: pool P (dedicated, granted to org A) holds nodes n1–n2; node n3 is unassigned (shared). One fractional 16 GB card per node. @@ -248,7 +248,7 @@ async def test_assert_may_grant_sub_assignment_rule(): assert_may_grant(su, other, grants, "org", org_b, None) -# 9 — active preemption honours pools: never yield a card the preemptor cannot borrow. +# 9 — active preemption honors pools: never yield a card the preemptor cannot borrow. async def _resident_on(db, f, dev_id: str, user_id: str, group: Project) -> SessionRow: """A running exclusive yield-mode resident (priority 0) holding ``dev_id``.""" resident = SessionRow( diff --git a/backend/tests/test_pilot_fixes.py b/backend/tests/test_pilot_fixes.py index 589059a..6e8678b 100644 --- a/backend/tests/test_pilot_fixes.py +++ b/backend/tests/test_pilot_fixes.py @@ -4,7 +4,7 @@ instead of queueing forever (e.g. exclusive against an all-fractional pool). - Stop-as-cancel: stopping a session that has not started yet (pending/preparing) cancels it (terminate + settle) instead of answering 409 invalid transition. -- Image catalogue: registry is PATCHable; DELETE removes an unused image and refuses one with +- Image catalog: registry is PATCHable; DELETE removes an unused image and refuses one with session history. """ from __future__ import annotations @@ -35,7 +35,7 @@ def _seed(db_objs): - """Common catalogue seed: org/group, funded wallet, offering, image, one fractional device.""" + """Common catalog seed: org/group, funded wallet, offering, image, one fractional device.""" org_id = ids.new("org") group = Project(id=ids.new("group"), org_id=org_id, name="p") user = user_row() @@ -113,7 +113,7 @@ async def test_exclusive_without_matching_pool_is_unserviceable(db, fake_handoff @pytest.mark.asyncio async def test_full_fractional_pool_still_queues(db, fake_handoff): - """A serviceable-but-currently-full request keeps the existing queue behaviour.""" + """A serviceable-but-currently-full request keeps the existing queue behavior.""" objs: list = [] group, user_id, wallet, cluster_id, offering, image, dev = _seed(objs) async with db.begin(): diff --git a/backend/tests/test_scheduler_logic.py b/backend/tests/test_scheduler_logic.py index c07f2fe..80533af 100644 --- a/backend/tests/test_scheduler_logic.py +++ b/backend/tests/test_scheduler_logic.py @@ -113,7 +113,7 @@ def test_reserve_exclusive_none_when_no_free_card(): def test_reserve_fractional_best_fit(): """Fractional: among the cards the slice fits on, pick the one with the least VRAM left, which - minimises fragmentation.""" + minimizes fragmentation.""" roomy = _dev(used_mem=0, used_cores=0, total_mem=40000, did="roomy") # 40000 free tight = _dev(used_mem=30000, used_cores=0, total_mem=40000, did="tight") # 10000 free target, eff_mem, eff_cores = SchedulerService._reserve_target( diff --git a/backend/tests/test_tenant_isolation.py b/backend/tests/test_tenant_isolation.py index 561526d..5b917f3 100644 --- a/backend/tests/test_tenant_isolation.py +++ b/backend/tests/test_tenant_isolation.py @@ -437,7 +437,7 @@ async def test_list_images_member_never_sees_other_users_private_images(db): res = await list_images(pagination=Pagination(1, 50), kind=None, q=None, tag=None, public=None, mine=False, principal=me, db=db) assert {r["id"] for r in res["data"]} == {"img_pub", "img_mine"} - # super_admin catalogue view is unchanged. + # super_admin catalog view is unchanged. res = await list_images(pagination=Pagination(1, 50), kind=None, q=None, tag=None, public=None, mine=False, principal=_super(), db=db) assert len(res["data"]) == 4 diff --git a/build/images/build.sh b/build/images/build.sh index 4203cb0..bb94b28 100755 --- a/build/images/build.sh +++ b/build/images/build.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash set -euo pipefail -# Build the catalogue session images, and optionally push them. +# Build the catalog session images, and optionally push them. # ./build.sh # build all four images # REG=myreg ./build.sh # registry namespace (default: boanlab) # REG=10.0.0.5:5000 ./build.sh push # push to a LAN registry instead of Docker Hub diff --git a/build/images/ml/Dockerfile.cpu b/build/images/ml/Dockerfile.cpu index 4505353..a08d070 100644 --- a/build/images/ml/Dockerfile.cpu +++ b/build/images/ml/Dockerfile.cpu @@ -1,7 +1,7 @@ # CPU session image on Ubuntu 24.04: code-server, JupyterLab, ttyd, and a data-science stack. No GPU. -# It honours the same connection contract as session-base — the same ports, paths, and entrypoint — +# It honors the same connection contract as session-base — the same ports, paths, and entrypoint — # and runs as non-root (uid 1000), which satisfies restricted Pod Security. -# Catalogue entry: name="Python ML (CPU · Ubuntu 24.04)", tag=ubuntu24.04-cpu-ml +# Catalog entry: name="Python ML (CPU · Ubuntu 24.04)", tag=ubuntu24.04-cpu-ml # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.cpu22 b/build/images/ml/Dockerfile.cpu22 index 17a24b3..268accd 100644 --- a/build/images/ml/Dockerfile.cpu22 +++ b/build/images/ml/Dockerfile.cpu22 @@ -5,9 +5,9 @@ # PyTorch build installs it themselves on top of a clean OS. 22.04 exists alongside 24.04 because # some vendor toolchains still pin to jammy. # -# It honours the same connection contract as session-base — the same ports, paths, and entrypoint — +# It honors the same connection contract as session-base — the same ports, paths, and entrypoint — # and runs as non-root (uid 1000), which satisfies restricted Pod Security. -# Catalogue entry: name="Ubuntu 22.04", tag=ml-ubuntu22.04 +# Catalog entry: name="Ubuntu 22.04", tag=ml-ubuntu22.04 # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.ml-cu128 b/build/images/ml/Dockerfile.ml-cu128 index bb1eb08..234dfba 100644 --- a/build/images/ml/Dockerfile.ml-cu128 +++ b/build/images/ml/Dockerfile.ml-cu128 @@ -1,7 +1,7 @@ # Base ML image on GPU: a CUDA runtime plus the three GShare connection tools and a data-science # stack. A GPU-capable Python environment with no deep-learning framework pinned, so users install # PyTorch or TensorFlow themselves if they want one. -# Catalogue entry: name="Python ML · CUDA 12.4 · cuDNN 9 (GPU)", tag=ml-cuda12.4-cudnn9-gpu +# Catalog entry: name="Python ML · CUDA 12.4 · cuDNN 9 (GPU)", tag=ml-cuda12.4-cudnn9-gpu # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.ml-gpu b/build/images/ml/Dockerfile.ml-gpu index 86e4bc0..16d8b69 100644 --- a/build/images/ml/Dockerfile.ml-gpu +++ b/build/images/ml/Dockerfile.ml-gpu @@ -1,7 +1,7 @@ # Base ML image on GPU: a CUDA runtime plus the three GShare connection tools and a data-science # stack. A GPU-capable Python environment with no deep-learning framework pinned, so users install # PyTorch or TensorFlow themselves if they want one. -# Catalogue entry: name="Python ML · CUDA 12.4 · cuDNN 9 (GPU)", tag=ml-cuda12.4-cudnn9-gpu +# Catalog entry: name="Python ML · CUDA 12.4 · cuDNN 9 (GPU)", tag=ml-cuda12.4-cudnn9-gpu # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.pytorch-blackwell b/build/images/ml/Dockerfile.pytorch-blackwell index ac6279e..0cbbae6 100644 --- a/build/images/ml/Dockerfile.pytorch-blackwell +++ b/build/images/ml/Dockerfile.pytorch-blackwell @@ -1,6 +1,6 @@ # PyTorch on GPU: the official PyTorch image, which guarantees a matching CUDA and cuDNN pair, plus # the three GShare connection tools and SciPy. -# Catalogue entry: name="PyTorch 2.6 · CUDA 12.4 (GPU)", tag=pytorch2.6-cuda12.4-cudnn9 +# Catalog entry: name="PyTorch 2.6 · CUDA 12.4 (GPU)", tag=pytorch2.6-cuda12.4-cudnn9 # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.pytorch-gpu b/build/images/ml/Dockerfile.pytorch-gpu index d4dc0f6..d1e018b 100644 --- a/build/images/ml/Dockerfile.pytorch-gpu +++ b/build/images/ml/Dockerfile.pytorch-gpu @@ -1,6 +1,6 @@ # PyTorch on GPU: the official PyTorch image, which guarantees a matching CUDA and cuDNN pair, plus # the three GShare connection tools and SciPy. -# Catalogue entry: name="PyTorch 2.6 · CUDA 12.4 (GPU)", tag=pytorch2.6-cuda12.4-cudnn9 +# Catalog entry: name="PyTorch 2.6 · CUDA 12.4 (GPU)", tag=pytorch2.6-cuda12.4-cudnn9 # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.pytorch28 b/build/images/ml/Dockerfile.pytorch28 index dff63a1..614048a 100644 --- a/build/images/ml/Dockerfile.pytorch28 +++ b/build/images/ml/Dockerfile.pytorch28 @@ -1,6 +1,6 @@ # PyTorch on GPU: the official PyTorch image, which guarantees a matching CUDA and cuDNN pair, plus # the three GShare connection tools and SciPy. -# Catalogue entry: name="PyTorch 2.6 · CUDA 12.4 (GPU)", tag=pytorch2.6-cuda12.4-cudnn9 +# Catalog entry: name="PyTorch 2.6 · CUDA 12.4 (GPU)", tag=pytorch2.6-cuda12.4-cudnn9 # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.tensorflow-gpu b/build/images/ml/Dockerfile.tensorflow-gpu index 595dd60..84d7669 100644 --- a/build/images/ml/Dockerfile.tensorflow-gpu +++ b/build/images/ml/Dockerfile.tensorflow-gpu @@ -1,6 +1,6 @@ # TensorFlow on GPU: the official TensorFlow GPU image, which guarantees a matching CUDA and cuDNN # pair, plus the three GShare connection tools and SciPy. -# Catalogue entry: name="TensorFlow 2.18 (GPU)", tag=tensorflow2.18-gpu +# Catalog entry: name="TensorFlow 2.18 (GPU)", tag=tensorflow2.18-gpu # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/ml/Dockerfile.tensorflow-ngc b/build/images/ml/Dockerfile.tensorflow-ngc index 2ba084e..6b269b3 100644 --- a/build/images/ml/Dockerfile.tensorflow-ngc +++ b/build/images/ml/Dockerfile.tensorflow-ngc @@ -1,6 +1,6 @@ # TensorFlow with Blackwell (sm_120) support: NVIDIA NGC's TF build (25.xx line supports Blackwell), # plus the three GShare connection tools. Hub's tensorflow/tensorflow images ship an older CUDA and -# do not run on RTX PRO 5000/6000. Catalogue entry: cuda_version=12.8. +# do not run on RTX PRO 5000/6000. Catalog entry: cuda_version=12.8. # Build context: build/images, so session-base/entrypoint.sh can be shared. FROM codercom/code-server:4.135.0 AS cs diff --git a/build/images/session-base/Dockerfile.cuda b/build/images/session-base/Dockerfile.cuda index 4c51954..60dc8a8 100644 --- a/build/images/session-base/Dockerfile.cuda +++ b/build/images/session-base/Dockerfile.cuda @@ -1,6 +1,6 @@ # The GShare GPU session image: a CUDA runtime plus the interactive session tools (VS Code, # JupyterLab, web terminal). -# It honours the same connection contract as session-base — the same ports, paths, and entrypoint — +# It honors the same connection contract as session-base — the same ports, paths, and entrypoint — # with only the base swapped for CUDA. # code-server is copied from its official image in a multi-stage build, bundled Node included. Runs as # non-root (uid 1000). diff --git a/charts/gshare/templates/configmap.yaml b/charts/gshare/templates/configmap.yaml index d2a9d22..0917ef6 100644 --- a/charts/gshare/templates/configmap.yaml +++ b/charts/gshare/templates/configmap.yaml @@ -28,7 +28,7 @@ data: # to ready when reports resume); super_admins are notified on each transition. GSHARE_NODE_STALE_SEC: {{ .Values.api.nodeStaleSec | default 300 | quote }} # Capacity (GB) of the pool backing user volumes, for the admin dashboard; 0 = unknown. - # Seed the Docker Hub session catalogue at startup; false for sites that run their own registry. + # Seed the Docker Hub session catalog at startup; false for sites that run their own registry. GSHARE_SEED_SESSION_IMAGES: {{ dig "api" "seedSessionImages" true (.Values | toYaml | fromYaml) | quote }} GSHARE_STORAGE_POOL_CAPACITY_GB: {{ dig "storage" "poolCapacityGb" 0 (.Values | toYaml | fromYaml) | quote }} # Fractional-slice placement across identical cards: binpack (fill the fullest card that diff --git a/charts/gshare/templates/operator-deployment.yaml b/charts/gshare/templates/operator-deployment.yaml index 64e515d..b6f0ac6 100644 --- a/charts/gshare/templates/operator-deployment.yaml +++ b/charts/gshare/templates/operator-deployment.yaml @@ -73,13 +73,13 @@ spec: - "--lossless-agent-image={{ . }}" {{- end }} {{- with .Values.operator.hamiMonitorUrl }} - # Where the idle reaper reads per-GPU utilisation: HAMi's vGPU monitor, which stock HAMi + # Where the idle reaper reads per-GPU utilization: HAMi's vGPU monitor, which stock HAMi # already runs, so no Prometheus is required. Activity-based and workload-aware, and it # takes precedence over prometheus-url. - "--hami-monitor-url={{ . }}" {{- end }} {{- with .Values.operator.prometheusUrl }} - # The alternative utilisation source: DCGM_FI_DEV_GPU_UTIL from Prometheus, used when + # The alternative utilization source: DCGM_FI_DEV_GPU_UTIL from Prometheus, used when # hami-monitor-url is unset. - "--prometheus-url={{ . }}" {{- end }} @@ -124,7 +124,7 @@ spec: {{- with .Values.operator.sessionImagePullPolicy }} # imagePullPolicy for session containers. IfNotPresent (the flag default) supports # air-gapped sites and locally imported images; Always re-checks the registry so a - # re-pushed fixed-tag catalogue image is picked up. + # re-pushed fixed-tag catalog image is picked up. - "--session-image-pull-policy={{ . }}" {{- end }} env: diff --git a/charts/gshare/values.yaml b/charts/gshare/values.yaml index eb5926e..aa049eb 100644 --- a/charts/gshare/values.yaml +++ b/charts/gshare/values.yaml @@ -79,7 +79,7 @@ api: # Seconds without an operator inventory report before a node is marked offline (and back to # ready when reports resume). super_admins are notified on each transition. nodeStaleSec: 300 - # Seed the boanlab/gshare-session catalogue images at startup. Sites serving session images + # Seed the boanlab/gshare-session catalog images at startup. Sites serving session images # from a private registry register them by hand and set this to false. seedSessionImages: true # Placement policy for fractional GPU slices when several cards fit: binpack | spread. @@ -139,7 +139,7 @@ operator: # (--connect-verify-url) point here. Required when controlPlane.enabled is false. # It must be reachable from both the operator pod and ingress-nginx. controlPlaneUrl: "" - # Where the idle reaper gets per-GPU utilisation. With neither set, idle GPU reclamation is + # Where the idle reaper gets per-GPU utilization. With neither set, idle GPU reclamation is # disabled and only the max-runtime cap applies — on a shared fleet that is the single most # expensive switch to leave off, so the HAMi monitor is the DEFAULT. Set hamiMonitorUrl to "" # explicitly to disable reclamation. @@ -166,7 +166,7 @@ operator: # Per-card GPU pools (flag-gated rollout): pool membership becomes a per-CARD ledger fact — # every GPU session flows through hami-scheduler pinned to the reserved card, exclusive is a # 100% HAMi slice, and gshare.io/gpu-mode node labels stop mattering for placement. Off keeps - # the legacy node-pool behaviour exactly. + # the legacy node-pool behavior exactly. perCardMode: false # StorageClass for session-volume PVCs (the operator ensures one PVC per volume on first # mount). Empty uses the cluster default StorageClass — local-path on the bootstrap cluster, @@ -180,7 +180,7 @@ operator: volumeSyncInterval: 5m # imagePullPolicy for session containers. IfNotPresent (the default) lets locally imported and # air-gapped images run; set Always to re-check the registry on every session start so that a - # re-pushed fixed-tag catalogue image is picked up. + # re-pushed fixed-tag catalog image is picked up. sessionImagePullPolicy: IfNotPresent # Full image reference for the lossless-pause and in-place-yield node agent. Left empty, the # checkpointer is disabled: pause falls back to cold, and neither in-place yield nor graceful diff --git a/deploy/monitoring/monitoring-stack.yaml b/deploy/monitoring/monitoring-stack.yaml index 0a5ebfc..edb80d8 100644 --- a/deploy/monitoring/monitoring-stack.yaml +++ b/deploy/monitoring/monitoring-stack.yaml @@ -4,7 +4,7 @@ # kubectl apply -f deploy/monitoring/monitoring-stack.yaml # # What runs: -# dcgm-exporter DaemonSet on GPU nodes -> DCGM_FI_DEV_* per physical card (UUID labelled) +# dcgm-exporter DaemonSet on GPU nodes -> DCGM_FI_DEV_* per physical card (UUID labeled) # node-exporter DaemonSet on every node -> host CPU / memory / disk / network # kube-state-metrics Deployment -> pod/node object state (restarts, phases) # kubelet cAdvisor scraped in-place -> per-pod CPU / memory / net / disk diff --git a/deploy/registry/registry.yaml b/deploy/registry/registry.yaml index bb9b69c..8c0a287 100644 --- a/deploy/registry/registry.yaml +++ b/deploy/registry/registry.yaml @@ -3,7 +3,7 @@ # # registry (:5000, hostPort on gshare-storage) — push target for locally built session images. # mirror (:5001, hostPort on gshare-storage) — pull-through cache of docker.io, so public -# catalogue images are fetched from the LAN after the first pull. +# catalog images are fetched from the LAN after the first pull. # # Plain HTTP on a trusted LAN (same layout as the bootstrap script's LOCAL_REGISTRY support); # moving to TLS later only changes the certs.d contents, not this manifest. Node trust lives in @@ -11,7 +11,7 @@ # LOCAL_REGISTRY=:5000 and LOCAL_REGISTRY_MIRROR=:5001). GC: `registry # garbage-collect` can be run in the pod. # -# Pinning: the storage node labelled by `cluster-bootstrap.sh label storage` +# Pinning: the storage node labeled by `cluster-bootstrap.sh label storage` # (gshare.io/role=storage). No storage node? Point nodeSelector at any node with disk and adjust # storageClassName below (gshare-data comes from the optional ZFS/democratic-csi step). apiVersion: v1 diff --git a/deploy/values/dataplane.yaml b/deploy/values/dataplane.yaml index 0dad567..e76a4c3 100644 --- a/deploy/values/dataplane.yaml +++ b/deploy/values/dataplane.yaml @@ -37,7 +37,7 @@ bootstrapLocalCluster: false operator: # clusterId and controlPlaneUrl differ per cluster and are injected with --set by # `make deploy-dataplane`. - # The idle reaper reads utilisation from the stock HAMi vGPU monitor that cluster-bootstrap + # The idle reaper reads utilization from the stock HAMi vGPU monitor that cluster-bootstrap # installs, so no Prometheus is required. hamiMonitorUrl: "http://hami-device-plugin-monitor.kube-system.svc:31992" # With a storage node (cluster-info STORAGE_NODE): the democratic-csi class that gives volumes a diff --git a/deploy/values/incluster.yaml b/deploy/values/incluster.yaml index ae38b09..66eaf3d 100644 --- a/deploy/values/incluster.yaml +++ b/deploy/values/incluster.yaml @@ -38,7 +38,7 @@ operator: # failurePolicy=Ignore. webhook: enabled: true - # The idle reaper reads utilisation from HAMi's vGPU monitor, which the stock HAMi installed by + # The idle reaper reads utilization from HAMi's vGPU monitor, which the stock HAMi installed by # cluster-bootstrap already runs. That gives workload-aware idle reclamation with no separate # monitoring stack. If you run your own Prometheus, use prometheusUrl instead. hamiMonitorUrl: "http://hami-device-plugin-monitor.kube-system.svc:31992" diff --git a/docs/README.md b/docs/README.md index d439b2e..4fc2ccc 100644 --- a/docs/README.md +++ b/docs/README.md @@ -35,7 +35,7 @@ in **fractional** or **exclusive** mode — and accounts for what they use in ** - [**User manual**](user-manual.md) — login, dashboard, sessions, wallet, volumes, and account settings, screen by screen. - [**Administrator manual**](admin-manual.md) — organizations, groups, users, resource - catalogue and policy, credit allocation, clusters and nodes, session monitoring, audit. + catalog and policy, credit allocation, clusters and nodes, session monitoring, audit. ### Deploying and operating @@ -59,5 +59,5 @@ in **fractional** or **exclusive** mode — and accounts for what they use in ** needs only the control plane. > The root [`README.md`](../README.md) and the code are the authority on current -> behaviour. These documents sit on top of that to help you learn, use, and operate the +> behavior. These documents sit on top of that to help you learn, use, and operate the > platform. diff --git a/docs/admin-manual.md b/docs/admin-manual.md index 3817c45..abcb974 100644 --- a/docs/admin-manual.md +++ b/docs/admin-manual.md @@ -7,7 +7,7 @@ title: Administrator guide The **administrator console** is where organizations, groups, and users are managed; credits allocated and requests decided; sessions monitored; and — for the platform administrator — the -GPU catalogue, policy, clusters, nodes, storage, images and system settings configured. +GPU catalog, policy, clusters, nodes, storage, images and system settings configured. Start with [Roles and scope](./admin/roles.md): what each administrative role sees is the key to every page that follows. @@ -34,16 +34,16 @@ The day-to-day of an organization or group administrator. Super administrator only. -- [Resources and policy](./admin/resources.md) — catalogue versus quota. +- [Resources and policy](./admin/resources.md) — catalog versus quota. - [Offerings](./admin/resources-offerings.md) — GPU models, model strings, rates. - [Presets](./admin/resources-presets.md) — compute shapes and GPU tiers. - [Resource policies](./admin/resources-policies.md) — quotas, timeouts, quota requests. - [Clusters](./admin/clusters.md) — registering, session domains, deregistering. - [Nodes](./admin/nodes.md) — liveness, cordon, drain, delete. - [Node pools](./admin/node-pools.md) — dedicated hardware and the spill question. -- [GPU devices](./admin/gpus.md) — aliases, faulty cards, allocation versus utilisation. +- [GPU devices](./admin/gpus.md) — aliases, faulty cards, allocation versus utilization. - [Storage](./admin/storage.md) — pools, every volume, running out of space. -- [Images](./admin/images.md) — importing, building, keeping the catalogue small. +- [Images](./admin/images.md) — importing, building, keeping the catalog small. - [Metrics](./admin/platform-monitoring.md) — DCGM and host metrics, and what they tell you. - [System settings](./admin/system.md) — branding, sign-up policy, GPU placement. diff --git a/docs/admin/audit.md b/docs/admin/audit.md index d775b5f..6447a04 100644 --- a/docs/admin/audit.md +++ b/docs/admin/audit.md @@ -64,4 +64,4 @@ everything. | Who ended other people's sessions this week? | Action = `session.force_terminate`, period = 1 week | | Where did this organization's credits go? | Actor = the org admin, action = `credit.*` | | Is someone probing for access they lack? | Result = denied | -| Who changed the GPU catalogue? | Action = `offering.*` | +| Who changed the GPU catalog? | Action = `offering.*` | diff --git a/docs/admin/credits-allocate.md b/docs/admin/credits-allocate.md index 1c33cf9..9c10692 100644 --- a/docs/admin/credits-allocate.md +++ b/docs/admin/credits-allocate.md @@ -54,7 +54,7 @@ The band under it reconciles the figures: system balance, monthly total, the sum organizations, and what is left to allocate. Then one row per organization with the same allocate / reclaim / monthly-refill controls. -:::tip Refill beats hand-outs +:::tip[Refill beats hand-outs] For anything recurring — a class, a lab, a standing budget — set a **monthly refill** rather than allocating by hand. It keeps working when nobody is watching, and the ledger shows exactly the same rows. diff --git a/docs/admin/dashboard.md b/docs/admin/dashboard.md index 377fe50..e510472 100644 --- a/docs/admin/dashboard.md +++ b/docs/admin/dashboard.md @@ -5,7 +5,7 @@ title: Dashboard # Administrator dashboard -The first screen of the administrator console summarises what is running **within your scope**. +The first screen of the administrator console summarizes what is running **within your scope**. ## As an organization or group administrator @@ -17,7 +17,7 @@ sessions**, **active sessions**, the **VRAM** those sessions hold, and the **CPU against the fleet. The sessions themselves are on the [monitor](./monitoring.md), credits on the [allocation page](./credits-allocate.md). -Cluster-wide figures — fleet utilisation, node health, storage — are deliberately super_admin +Cluster-wide figures — fleet utilization, node health, storage — are deliberately super_admin only: a tenant administrator manages people, not machines. ## As the platform administrator @@ -27,7 +27,7 @@ only: a tenant administrator manages people, not machines. | Panel | What it answers | |---|---| | **Active sessions · Queue** | Is anything waiting, and how much is running | -| **GPU utilisation · VRAM occupancy** | Allocation against real usage — a fleet allocated to 90% but used at 20% is a policy problem, not a capacity one | +| **GPU utilization · VRAM occupancy** | Allocation against real usage — a fleet allocated to 90% but used at 20% is a policy problem, not a capacity one | | **Empty GPUs** | Cards with nothing on them right now | | **Credits in the last 24h** | Spend rate across the platform, with active holds | | **GPU devices** | One tile per card: cluster tag, mode, VRAM occupancy, free cores | diff --git a/docs/admin/gpus.md b/docs/admin/gpus.md index 6552429..0e93c24 100644 --- a/docs/admin/gpus.md +++ b/docs/admin/gpus.md @@ -14,7 +14,7 @@ Every card the fleet reports, with what is on it right now. | **Node / cluster** | Where the card is | | **Model** | The driver's exact string — this is what an [offering](./resources-offerings.md) must match | | **Alias** | A human name you can give the card | -| **VRAM (used / total) · cores** | Allocation, not live utilisation | +| **VRAM (used / total) · cores** | Allocation, not live utilization | | **Mode** | fractional or exclusive | | **Bound sessions** | The sessions holding slices of it | | **Target pool** | The [pool](./node-pools.md) it is moving to, if any | @@ -57,9 +57,9 @@ for a dead card. Fatal Xid events reported by DCGM cordon the **whole node** automatically. The card action is for the narrower case: one card of several is bad, and the rest of the machine is fine. -## Allocation is not utilisation +## Allocation is not utilization The VRAM figure here is what the ledger **reserved**. What the card is actually doing comes from -DCGM on the [monitoring page](./platform-monitoring.md). A fleet allocated to 90% and utilised +DCGM on the [monitoring page](./platform-monitoring.md). A fleet allocated to 90% and utilized at 15% is not short of hardware — it is short of idle timeouts and smaller [tiers](./resources-presets.md). diff --git a/docs/admin/groups.md b/docs/admin/groups.md index f515c9c..a5eb1f4 100644 --- a/docs/admin/groups.md +++ b/docs/admin/groups.md @@ -43,7 +43,7 @@ policy. - monitor and force-terminate their members' sessions, - read the group's audit entries. -They cannot create groups, touch other groups, or change the catalogue; the only policies +They cannot create groups, touch other groups, or change the catalog; the only policies they can set are their own group's and its members'. ## Deactivating and deleting diff --git a/docs/admin/images.md b/docs/admin/images.md index 4caa8a0..801c51e 100644 --- a/docs/admin/images.md +++ b/docs/admin/images.md @@ -5,7 +5,7 @@ title: Images # Images and templates -The image catalogue is what the session wizard offers. An image that is not here (or not +The image catalog is what the session wizard offers. An image that is not here (or not compatible with the chosen card) cannot be run. ![Images](/img/screens/admin-images.png) @@ -13,13 +13,13 @@ compatible with the chosen card) cannot be run. | Column | Meaning | |---|---| | **Name** | What users see | -| **Kind** | Catalogue image, or a user's own | +| **Kind** | Catalog image, or a user's own | | **Source** | The registry reference | | **CUDA** | The runtime inside — matched against the offering's minimum | | **Supported GPUs** | Models verified for it | | **Public** | Visible to everyone, or private to its owner — toggled from the row | -Two tabs: the **catalogue** itself, and **builds** — every console-driven build with its state +Two tabs: the **catalog** itself, and **builds** — every console-driven build with its state and log, whether it succeeded or not. ## Importing @@ -55,15 +55,15 @@ tagged **My image** in the wizard. ## Seeded images -With `api.seedSessionImages` (the default) the catalogue seeds `boanlab/gshare-session` for the +With `api.seedSessionImages` (the default) the catalog seeds `boanlab/gshare-session` for the CUDA 12.4/12.5 line and the Blackwell 12.8/12.9 line at startup. Those tags exist on Docker Hub only after the publish workflow has run for a release. A fleet of Blackwell cards needs the 12.8 line; older images are refused with -`incompatible_image` before the session starts, which is the behaviour you want — the alternative +`incompatible_image` before the session starts, which is the behavior you want — the alternative is a container that starts and then cannot see the GPU. -## Keeping the catalogue small +## Keeping the catalog small Every extra image is a decision for the user and 5–15 GiB on every node that pulls it. One maintained image per framework generation beats a dozen variants; let people build their own for diff --git a/docs/admin/node-pools.md b/docs/admin/node-pools.md index 88b0e06..c9f87aa 100644 --- a/docs/admin/node-pools.md +++ b/docs/admin/node-pools.md @@ -43,7 +43,7 @@ A tenant whose dedicated pool is full falls back to shared nodes **only if their decision: - **Spill allowed** — the department always gets its own cards first but can borrow idle shared - capacity. Best utilisation. + capacity. Best utilization. - **Spill denied** — the department is strictly capped at its own hardware. Predictable for everyone else, and the department's queue is entirely their own to manage. diff --git a/docs/admin/platform-monitoring.md b/docs/admin/platform-monitoring.md index 6e733f9..a95c7d7 100644 --- a/docs/admin/platform-monitoring.md +++ b/docs/admin/platform-monitoring.md @@ -3,7 +3,7 @@ sidebar_position: 26 title: Metrics --- -# Metrics and utilisation +# Metrics and utilization **Operations → Monitoring** charts what the hardware is actually doing, from DCGM and node-exporter through Prometheus. It is the counterpart to the allocation figures everywhere @@ -13,7 +13,7 @@ else in the console. | Tab | What it shows | |---|---| -| **GPU** | Per-card utilisation, VRAM in use, temperature and power, by node and by card | +| **GPU** | Per-card utilization, VRAM in use, temperature and power, by node and by card | | **Host** | CPU, memory, disk and network per node | The range selector and auto-refresh sit at the top; the node filter narrows to one machine. @@ -29,7 +29,7 @@ The table under the charts is the reconciliation that matters: A fractional card cannot be attributed to one session from the graph alone — several sessions share it — which is why both views exist. The pattern to look for: -| Allocation | Utilisation | Means | +| Allocation | Utilization | Means | |---|---|---| | High | High | Genuinely full. Buy hardware or tighten quotas | | High | Low | Idle reservations. Shorten the **idle timeout**, offer smaller [tiers](./resources-presets.md) | @@ -39,7 +39,7 @@ share it — which is why both views exist. The pattern to look for: Metrics need the monitoring stack: `make deploy-monitoring` installs Prometheus with the dcgm, node and kube-state exporters. Without it the console says the metrics backend is unreachable, -and — more importantly — the **idle reaper has no utilisation source** unless +and — more importantly — the **idle reaper has no utilization source** unless `operator.hamiMonitorUrl` or `operator.prometheusUrl` is set. Details, including what each exporter provides, are in diff --git a/docs/admin/resources-offerings.md b/docs/admin/resources-offerings.md index fe98c4a..9d12e2c 100644 --- a/docs/admin/resources-offerings.md +++ b/docs/admin/resources-offerings.md @@ -6,7 +6,7 @@ title: Offerings # GPU offerings An **offering** is one GPU model as a billable product. The session wizard is built from this -catalogue, and the scheduler prices against it. +catalog, and the scheduler prices against it. ![Offerings](/img/screens/admin-resources.png) @@ -24,7 +24,7 @@ catalogue, and the scheduler prices against it. ![New offering](/img/screens/admin-offering-new.png) -:::caution The model string must match exactly +:::caution[The model string must match exactly] Admission matches `gpu_model` to the string the driver reports, character for character — `NVIDIA GeForce RTX 4090`, not `RTX 4090`. **Copy it from [GPU devices](./gpus.md)** rather than typing it. diff --git a/docs/admin/resources-policies.md b/docs/admin/resources-policies.md index 87c262c..5a28abc 100644 --- a/docs/admin/resources-policies.md +++ b/docs/admin/resources-policies.md @@ -68,7 +68,7 @@ from their group, organization and global policies. Two habits keep this tidy: Rejecting asks for a reason the requester sees. Both decisions are audited and notified. -:::tip Credits or quota? +:::tip[Credits or quota?] If the user's error was *insufficient credits*, this queue is the wrong one — send them to [credit requests](./credits-requests.md). A quota increase does not add a single credit. ::: diff --git a/docs/admin/resources-presets.md b/docs/admin/resources-presets.md index 35c4187..a947d80 100644 --- a/docs/admin/resources-presets.md +++ b/docs/admin/resources-presets.md @@ -10,11 +10,11 @@ numbers behind them stay out of the way. ![Presets](/img/screens/admin-presets.png) -Two kinds sit in the same catalogue: +Two kinds sit in the same catalog: | Kind | What it fixes | |---|---| -| **Compute preset** | CPU cores, memory, scratch disk — *Compute S/M/L/XL* in the seeded catalogue | +| **Compute preset** | CPU cores, memory, scratch disk — *Compute S/M/L/XL* in the seeded catalog | | **GPU tier** | The fraction of a card: XL ½, L ¼, M ⅛, S 1/16, or exclusive | VRAM and cores for a tier are derived from the selected offering's whole-card figures, so one diff --git a/docs/admin/resources.md b/docs/admin/resources.md index 38b084a..4ffb9c8 100644 --- a/docs/admin/resources.md +++ b/docs/admin/resources.md @@ -10,7 +10,7 @@ confusion: | | What it is | Page | |---|---|---| -| **Catalogue** | What users may *choose* — GPU models and session sizes | [Offerings](./resources-offerings.md) · [Presets](./resources-presets.md) | +| **Catalog** | What users may *choose* — GPU models and session sizes | [Offerings](./resources-offerings.md) · [Presets](./resources-presets.md) | | **Policy** | What users may *hold* — quotas, timeouts, pool access | [Policies](./resources-policies.md) | Both are super_admin territory, except policy requests, which a tenant administrator can see for @@ -34,10 +34,10 @@ flowchart LR - A **preset** is a ready-made size: compute shape plus a fraction of a card. - A **policy** decides whether this user may hold that much at all. -A session is admitted only when the catalogue offers it, the policy allows it, and the wallet +A session is admitted only when the catalog offers it, the policy allows it, and the wallet covers it. -![Offering catalogue](/img/screens/admin-resources.png) +![Offering catalog](/img/screens/admin-resources.png) ## The order to set things up diff --git a/docs/admin/roles.md b/docs/admin/roles.md index 0e5fbbb..0b0e6b9 100644 --- a/docs/admin/roles.md +++ b/docs/admin/roles.md @@ -34,7 +34,7 @@ The [Tenant administration](./dashboard.md) pages are what an org_admin or group with day to day: [people](./users.md), [credits](./credits.md), what is [running](./monitoring.md), [what happened](./audit.md). The [Platform administration](./resources.md) pages are super_admin only and describe the machine -side: the [GPU catalogue](./resources-offerings.md), [clusters](./clusters.md) and +side: the [GPU catalog](./resources-offerings.md), [clusters](./clusters.md) and [nodes](./nodes.md), [storage](./storage.md), [images](./images.md), [system settings](./system.md). diff --git a/docs/admin/storage.md b/docs/admin/storage.md index 5d37310..ae47fd3 100644 --- a/docs/admin/storage.md +++ b/docs/admin/storage.md @@ -34,7 +34,7 @@ The order is: label the node, install the driver, register the pool. | **Pool name** | The linked node's **hostname**, always — typed only for a server the cluster never sees as a node | | **Cluster** | The cluster the server sits in. Fixed after registration | | **StorageClass** | The class that provisions from it — the same name the operator was given | -| **Storage node** | Optional. The labelled node; its disk becomes the fallback capacity | +| **Storage node** | Optional. The labeled node; its disk becomes the fallback capacity | | **Stated capacity (GB)** | The real pool size, used until the driver publishes one | | **Sharing** | *All clusters* — every cluster may place volumes here; *Selected* — tick the clusters allowed, besides this one | @@ -51,7 +51,7 @@ Each row shows the figure and its source, in order of preference: 1. **csi** — the driver's own `GetCapacity`, published as `CSIStorageCapacity` and read by the operator. The only automatic source. 2. **manual** — the figure stated on the pool. Set it when the driver publishes nothing. -3. **node disk** — the storage node's system drive, labelled as the stand-in it is. +3. **node disk** — the storage node's system drive, labeled as the stand-in it is. Several servers are several pools. A volume lives on exactly one, so the bound is the **largest** usable pool, never the sum. The operator-side detail — driver flags, NFS diff --git a/docs/admin/system.md b/docs/admin/system.md index 4b910ac..3bc11fe 100644 --- a/docs/admin/system.md +++ b/docs/admin/system.md @@ -22,7 +22,7 @@ Changing the name is the quickest way to make a staging instance visibly *not* p ![Sign-up policy](/img/screens/admin-system-signup.png) -| Mode | Behaviour | +| Mode | Behavior | |---|---| | **Closed** | No sign-up tab on the sign-in screen. Administrators create every account | | **Approval** | Anyone may register; the account is **pending** until an administrator approves it | @@ -42,7 +42,7 @@ approved without one can sign in and do nothing. Which card a fractional session lands on when several qualify: -| Policy | Behaviour | Use when | +| Policy | Behavior | Use when | |---|---|---| | **Binpack** | Fills the busiest qualifying card first | You want whole cards left free for large sessions — the usual default | | **Spread** | Uses the emptiest card first | You want each session to have the most headroom, at the cost of fragmenting the fleet | diff --git a/docs/admin/users-add.md b/docs/admin/users-add.md index 26953fa..8b805be 100644 --- a/docs/admin/users-add.md +++ b/docs/admin/users-add.md @@ -57,7 +57,7 @@ able to sign in but unable to run anything, which is a support ticket waiting to There is no separate reject: to decline a sign-up, **delete** the pending account from its row. The person can register again. -:::tip Restrict the domain +:::tip[Restrict the domain] The sign-up policy also takes a list of **allowed email domains**. Set it to your own (`example.com`) so a stray address cannot queue for approval in the first place. See [System settings](./system.md#sign-up). diff --git a/docs/admin/users-manage.md b/docs/admin/users-manage.md index b9bd12a..6630a5d 100644 --- a/docs/admin/users-manage.md +++ b/docs/admin/users-manage.md @@ -63,7 +63,7 @@ What happens (a *soft* delete, which is what the console does): A *hard* delete exists in the API for the super_admin, and only for an account with no session history at all; it removes memberships, share permissions and an empty wallet. -:::caution Deactivate first, delete later +:::caution[Deactivate first, delete later] For someone who has simply left, deactivation is almost always the right action: it stops access at once and leaves you a week to find out what of theirs the team still depends on. ::: diff --git a/docs/architecture.md b/docs/architecture.md index 2885a28..1421cc0 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -27,7 +27,7 @@ resources, so that many organizations, groups, and users can share one cluster. ▼ control plane (backend, Python/FastAPI) ── owns state and money: authentication, │ ├ gshare-api : admission, CRUD, token issuing authorization, credits, - │ └ gshare-worker : billing, budget rollup, queue, budgets, catalogue, + │ └ gshare-worker : billing, budget rollup, queue, budgets, catalog, │ refills policy, scheduling │ applies GShareSession CR (via kubeconfig) ▲ signed status and inventory ▼ │ callbacks (internal JWT) @@ -53,9 +53,9 @@ about money and state are made only in the control plane. ## Core concepts -- **Offering** — the catalogue of GPU models. One row per full-card model, carrying the +- **Offering** — the catalog of GPU models. One row per full-card model, carrying the hourly credit rate. Chosen when a session is created. -- **Preset** — the catalogue of session sizes: compute (CPU, memory, disk) plus a GPU +- **Preset** — the catalog of session sizes: compute (CPU, memory, disk) plus a GPU fraction tier (XL ½, L ¼, M ⅛, S 1/16) or an exclusive full card. VRAM and core limits are derived by applying the tier fraction to the offering's full-card VRAM. - **Session** — an interactive working environment, backed by a pod. Its mode is either diff --git a/docs/cluster-setup.md b/docs/cluster-setup.md index dcc9e96..c2210a5 100644 --- a/docs/cluster-setup.md +++ b/docs/cluster-setup.md @@ -40,10 +40,10 @@ cp hack/cluster-info.example hack/cluster-info # fill in MASTER_NODE and WORKE MASTER_NODE=ubuntu@10.0.0.10 # Workers are user@ip:MODE, where MODE is exclusive or fractional (default: fractional). WORKER_NODES=ubuntu@10.10.0.196:exclusive,ubuntu@10.10.0.197:fractional -# Optional GPU-less workers, comma separated. Labelled `cpu`; the NVIDIA runtime is not installed. +# Optional GPU-less workers, comma separated. Labeled `cpu`; the NVIDIA runtime is not installed. # CPU_WORKERS=ubuntu@10.10.0.200,ubuntu@10.10.0.201 # Optional storage node: a ZFS pool on the given (empty) block device, exported over NFS through -# democratic-csi as StorageClass gshare-data. Labelled and tainted `storage`. +# democratic-csi as StorageClass gshare-data. Labeled and tainted `storage`. # STORAGE_NODE=ubuntu@10.10.0.194:/dev/vdb # Optional plain-HTTP registry on the LAN, configured for containerd on every node. # LOCAL_REGISTRY=10.10.0.191:5001 @@ -53,7 +53,7 @@ WORKER_NODES=ubuntu@10.10.0.196:exclusive,ubuntu@10.10.0.197:fractional `up` copies the script to every node and then runs, in order: prerequisites (control plane, CPU workers, and GPU workers in parallel) → reboot and reconnect any GPU worker that just got a driver → `kubeadm init` on the control plane, harvesting the join command → workers -join (GPU and CPU in parallel) → addons on the control plane → node labelling (control +join (GPU and CPU in parallel) → addons on the control plane → node labeling (control plane and CPU workers as `cpu`, GPU workers with their configured mode) → verification. `hack/cluster-info` contains real addresses and is git-ignored; only @@ -98,7 +98,7 @@ disables swap, and installs kubeadm, kubelet, and kubectl 1.36. When a driver is installed the script asks for a reboot; add `NVIDIA_DRIVER_REBOOT=1` to have it reboot itself. -### 2. Control plane — initialise +### 2. Control plane — initialize ```bash sudo ./hack/cluster-bootstrap.sh init @@ -181,7 +181,7 @@ every node. Two pieces, both optional: 1. **The registry itself** — `deploy/registry/registry.yaml` runs two plain-HTTP registries on the storage node (`gshare.io/role=storage`): a push target on `:5000` for locally built session - images, and a docker.io **pull-through mirror** on `:5001` so public catalogue images are + images, and a docker.io **pull-through mirror** on `:5001` so public catalog images are fetched from the LAN after the first pull. `kubectl apply -f deploy/registry/registry.yaml` (adjust the nodeSelector / storageClassName in the header if your layout differs). 2. **Node trust** — containerd on every node must be told about them: @@ -198,11 +198,11 @@ every node. Two pieces, both optional: `LOCAL_REGISTRY` is set in `cluster-info`. Moving to TLS later means dropping the CA next to `hosts.toml`; the layout stays. -Build and push the catalogue images to it from any docker host that lists the registry under +Build and push the catalog images to it from any docker host that lists the registry under `"insecure-registries"`: ```bash -REG=:5000 build/images/build.sh push # builds all catalogue images, pushes to the LAN +REG=:5000 build/images/build.sh push # builds all catalog images, pushes to the LAN ``` then register them in the console (Images → the registry reference is @@ -232,7 +232,7 @@ here interrupts running work: existing nodes are untouched. ``` 3. **On the control plane — label it.** Skipping this is the usual reason a new GPU node - advertises no capacity: HAMi only claims cards on nodes labelled `gpu=on`, and placement + advertises no capacity: HAMi only claims cards on nodes labeled `gpu=on`, and placement reads `gshare.io/gpu-mode`. ```bash @@ -277,7 +277,7 @@ Then, in GShare itself: 8. **Check the offering for that GPU model.** Admission matches `offering.gpu_model` to the device model by **string equality**, so a card whose model has no active offering is visible - to administrators but unusable — session creation answers `409 unserviceable`. The catalogue + to administrators but unusable — session creation answers `409 unserviceable`. The catalog row's "in cluster" tag under **Resources → GPU offerings** tells you which models are backed by real cards; create or activate an offering for a new model before announcing the capacity. @@ -346,7 +346,7 @@ CloudNativePG, Redis, and external-secrets, use `make prod-deploy` with are overwritten, the swap line is not commented twice, and addons use `apply` or `helm upgrade -i`. `init` probes the API server's `/healthz` to decide what to do — if it is healthy the step is skipped; if only leftovers from a previous init are present - (occupied ports, manifests, etcd data) it runs `kubeadm reset -f` and re-initialises. Set + (occupied ports, manifests, etcd data) it runs `kubeadm reset -f` and re-initializes. Set `INIT_FORCE_RESET=0` to be told about it instead. `join` is skipped when `kubelet.conf` exists. One exception: the containerd configuration is regenerated from defaults every time, so hand edits there are not preserved. diff --git a/docs/getting-started.md b/docs/getting-started.md index 4baf9e4..75c1625 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -92,7 +92,7 @@ cp hack/cluster-info.example hack/cluster-info # fill in MASTER_NODE, WORKER_N ./hack/cluster-bootstrap.sh up # kubeadm + flannel + HAMi + ingress-nginx(:30080) + local-path ``` -`up` labels the nodes according to the modes in `cluster-info`; manual labelling is only +`up` labels the nodes according to the modes in `cluster-info`; manual labeling is only needed on the step-by-step path. ### Step 1 — decide the domain and TLS @@ -145,7 +145,7 @@ example in [`domain.example.yaml`](../deploy/values/domain.example.yaml)): - **Monitoring** — `make deploy-monitoring` installs Prometheus with the dcgm / node / kube-state exporters. It powers the admin monitoring page, the per-session live-usage - panels, and (via `operator.prometheusUrl`) the idle reaper's utilisation source — on a + panels, and (via `operator.prometheusUrl`) the idle reaper's utilization source — on a cluster with more than one GPU node, set `prometheusUrl`; the HAMi-monitor fallback round-robins per-node pods and idle sessions are then never auto-paused. Prometheus keeps its data on a PVC of the cluster's **default StorageClass** — it does not need the optional storage node. (If an earlier install left a PVC pinned to `gshare-data`, delete that PVC before re-applying: `storageClassName` is immutable.) - **Mixed GPU fleet** — different card models in one cluster need @@ -171,9 +171,9 @@ kubectl get secret -n gshare-system gshare-bootstrap-admin -o jsonpath='{.data.p Open **https://gshare.example.com** through your reverse proxy and log in with `bootstrapAdmin.email` and that password. You will be asked to change it immediately. -### Step 4 — check the catalogue (administrator) +### Step 4 — check the catalog (administrator) -A default catalogue is seeded idempotently at startup: GPU offerings (RTX, A100, H100), +A default catalog is seeded idempotently at startup: GPU offerings (RTX, A100, H100), base images, compute and GPU presets, a global resource policy, and the system wallet. As an administrator you only edit and extend it, from the console or through `POST /api/v1/offerings` and `POST /api/v1/images` / `/images/import`. @@ -182,7 +182,7 @@ an administrator you only edit and extend it, from the console or through The seeded rates are suggestions — adjust them in the console. - An **image** is the session container image. The GShare session images ship JupyterLab, a web terminal, and code-server. -- Users are not limited to the shared catalogue: a member can register images of their own +- Users are not limited to the shared catalog: a member can register images of their own through the API (`POST /api/v1/images/import` for a public registry reference, `POST /api/v1/image-builds` for a build). Those rows are private to their owner, tagged **My image** in the wizard, and one member may hold at most 20 of them. diff --git a/docs/multi-cluster.md b/docs/multi-cluster.md index 976e423..bc6d0b2 100644 --- a/docs/multi-cluster.md +++ b/docs/multi-cluster.md @@ -186,7 +186,7 @@ In order, and each reading says which it used: only automatic source; nothing else can see past the node's root disk. 2. **`manual`** — the figure stated on the pool (`manual_capacity_gb`). The control-plane-wide `STORAGE_POOL_CAPACITY_GB` still works as a fleet default for a single-pool install. -3. **`node_disk`** — the storage node's system drive. A stand-in, labelled as one: on a ZFS box it +3. **`node_disk`** — the storage node's system drive. A stand-in, labeled as one: on a ZFS box it is a different disk from the pool and can be off by hundreds of gigabytes either way. `attach-cluster.sh` sets `csiDriver.storageCapacity=true` so a driver that supports capacity diff --git a/docs/operations/observability.md b/docs/operations/observability.md index cb46692..64b8802 100644 --- a/docs/operations/observability.md +++ b/docs/operations/observability.md @@ -19,7 +19,7 @@ installs into the `monitoring` namespace: | Component | Runs on | Provides | |---|---|---| -| dcgm-exporter | every GPU node | `DCGM_FI_DEV_*` per physical card, UUID-labelled | +| dcgm-exporter | every GPU node | `DCGM_FI_DEV_*` per physical card, UUID-labeled | | node-exporter | every node | host CPU, memory, disk, network | | kube-state-metrics | one pod | pod and node object state (restarts, phases) | | kubelet cAdvisor | scraped in place | per-pod CPU, memory, network, disk | @@ -32,7 +32,7 @@ which whitelists the queries and enforces the super_admin gate. ## Pointing the operator at it The idle reaper pauses GPU sessions whose card has been idle for the policy's idle timeout. It -needs a utilisation source: +needs a utilization source: - `operator.hamiMonitorUrl` (default) — HAMi's own monitor, no extra infrastructure. On a cluster with more than one GPU node the monitor round-robins per-node pods, so use Prometheus instead. diff --git a/docs/operations/storage.md b/docs/operations/storage.md index 5828283..8cf407f 100644 --- a/docs/operations/storage.md +++ b/docs/operations/storage.md @@ -52,7 +52,7 @@ as the bound, never the sum. topology the objects churn and nothing usable is published. 2. **`manual`** — the figure stated on the pool. `STORAGE_POOL_CAPACITY_GB` (`storage.poolCapacityGb` in the chart) still works as a fleet-wide default. -3. **`node_disk`** — the storage node's system drive, labelled as a stand-in. +3. **`node_disk`** — the storage node's system drive, labeled as a stand-in. The dashboard's storage tile names the source it used. diff --git a/docs/reference/api.md b/docs/reference/api.md index 81db609..b2e1d7b 100644 --- a/docs/reference/api.md +++ b/docs/reference/api.md @@ -9,7 +9,7 @@ Everything the console does goes through the public REST API at `/api/v1`. The r installation serves the OpenAPI document at `/api/v1/openapi.json` and Swagger UI at `/api/v1/docs`; the same document is checked into the repository as `frontend/openapi.json`. -:::note Scope +:::note[Scope] gShare is deliberately console-first: there are no API keys, CLI, or SDK. The API exists for the console and for operators automating administration with a user's own token. ::: @@ -54,7 +54,7 @@ endpoints until they do. | `/queue` | Queue entries, cancel, priority | | `/credits`, `/budgets` | Wallets, allocations, requests, refills, ledger; organization budgets | | `/storage/volumes`, `/storage/pools` | Volumes, shares, quota, locks; storage pools | -| `/offerings`, `/resource-presets`, `/images`, `/resource-policies` | The catalogue and policies, including quota requests | +| `/offerings`, `/resource-presets`, `/images`, `/resource-policies` | The catalog and policies, including quota requests | | `/clusters`, `/nodes`, `/gpu-devices`, `/node-pools` | Infrastructure: registration, cordon/drain/delete, cards, pools | | `/monitoring`, `/dashboard`, `/metrics` | Metrics proxies and summaries | | `/audit-logs` | Audit log with filters and CSV export | diff --git a/docs/reference/helm-values.md b/docs/reference/helm-values.md index aa4df31..8080475 100644 --- a/docs/reference/helm-values.md +++ b/docs/reference/helm-values.md @@ -40,7 +40,7 @@ knob). | `buildRegistry` | | Registry prefix for console-built images. | | `auditRetentionDays` | 180 | 0 disables pruning. | | `nodeStaleSec` | 300 | Silence before a node goes offline. | -| `seedSessionImages` | true | Seed the `boanlab/gshare-session` catalogue. | +| `seedSessionImages` | true | Seed the `boanlab/gshare-session` catalog. | | `gpuPacking` | binpack | `binpack` or `spread` for fractional placement. | | `volumeReclaimGraceHours` | 24 | Keep a deleted volume's data this long. | | `forwardedAllowIps` | `*` | Peers uvicorn trusts to set `X-Forwarded-*` (`--forwarded-allow-ips`); narrow to the ingress controller's addresses where possible. | @@ -57,7 +57,7 @@ knob). | `clusterId` | The cluster this operator reports as (`clu_local` for the all-in-one install). | | `controlPlaneUrl` | Where callbacks go when the control plane is elsewhere. | | `internalJwtSecret`, `internalJwtTokenTtlSec` | The operator's token and its TTL (re-signed daily by a CronJob). | -| `hamiMonitorUrl`, `prometheusUrl` | Utilisation source for the idle reaper; see [Observability](../operations/observability.md). | +| `hamiMonitorUrl`, `prometheusUrl` | Utilization source for the idle reaper; see [Observability](../operations/observability.md). | | `perCardMode` | Pin each session to the exact card reserved — required for a mixed-model fleet. | | `volumeStorageClass`, `volumeSyncInterval` | The pool's StorageClass and how often PVCs and capacity are reconciled. | | `sessionImagePullPolicy` | For session pods. | diff --git a/docs/user-manual.md b/docs/user-manual.md index 9574c6e..9e4d2cd 100644 --- a/docs/user-manual.md +++ b/docs/user-manual.md @@ -33,6 +33,6 @@ screens you use to run sessions, keep data, and manage credits. Administrative features — organizations, groups, users, credits, clusters, monitoring — are in the [Administrator guide](./admin-manual.md). -:::tip Only GPU time costs credits +:::tip[Only GPU time costs credits] CPU sessions and volumes are free. Your balance never falls while no GPU session is running. ::: diff --git a/docs/user/data-manage.md b/docs/user/data-manage.md index ac668aa..1d3c1d7 100644 --- a/docs/user/data-manage.md +++ b/docs/user/data-manage.md @@ -53,7 +53,7 @@ What happens next: Within that window an administrator can still recover the data. After it, nothing can. -:::caution There is no undo in the console +:::caution[There is no undo in the console] The confirmation is the last stop. Copy anything you are unsure about into another volume first — a volume costs you nothing but quota. ::: diff --git a/docs/user/data-share.md b/docs/user/data-share.md index bed65f5..e03037b 100644 --- a/docs/user/data-share.md +++ b/docs/user/data-share.md @@ -48,7 +48,7 @@ your own. What differs: owner — this is the polite way to tidy a list, not a way to delete someone's data. Ask the owner to share it again if you need it back. -:::caution Sharing is access, not a copy +:::caution[Sharing is access, not a copy] Everyone you share a read/write volume with can overwrite the files in it. For a dataset that must not change, share it read-only — or create it read-only in the first place. ::: diff --git a/docs/user/data.md b/docs/user/data.md index 81f9eaa..c11fb70 100644 --- a/docs/user/data.md +++ b/docs/user/data.md @@ -16,7 +16,7 @@ the session lands. | [Sharing a volume](./data-share.md) | Giving access, read-only or read/write, revoking | | [Resizing, locking, deleting](./data-manage.md) | Growing the quota, locking, safe deletion | -:::tip Volumes are free +:::tip[Volumes are free] Credits are charged for GPU session time only. What limits storage is the **quota** in your [resource policy](../admin/resources.md), shown on every volume, not your balance. ::: diff --git a/docs/user/sessions-connect.md b/docs/user/sessions-connect.md index 1288bc7..18440f4 100644 --- a/docs/user/sessions-connect.md +++ b/docs/user/sessions-connect.md @@ -32,7 +32,7 @@ why a link that has been sat on for a while, or forwarded to someone else, does The panel also shows the raw URL and the token with copy buttons, for pasting into a ticket or a script that has to reach the session. -:::caution The link is your access +:::caution[The link is your access] Anyone holding an unredeemed link can enter your session and your data. Treat it like a password: do not paste it into a shared channel. ::: diff --git a/docs/user/sessions-create.md b/docs/user/sessions-create.md index 4e5e11e..3e87713 100644 --- a/docs/user/sessions-create.md +++ b/docs/user/sessions-create.md @@ -41,7 +41,7 @@ four steps, and no credits. ![Session name](/img/screens/wiz-name.png) -A name is suggested (`gpu-MMDD-HHMM`). Replace it with something you will recognise in a list a +A name is suggested (`gpu-MMDD-HHMM`). Replace it with something you will recognize in a list a week from now — `resnet-finetune` beats `gpu-0911`. ### Cluster @@ -71,7 +71,7 @@ inside the session. Leave it off unless you need it. ![Compute presets](/img/screens/wiz-compute.png) The preset is the CPU, memory, and scratch disk of the container — independent of the GPU -choice. The seeded catalogue runs from **Compute S** (2 vCPU · 4 GiB · 20 GiB) to +choice. The seeded catalog runs from **Compute S** (2 vCPU · 4 GiB · 20 GiB) to **Compute XL** (16 vCPU · 24 GiB · 200 GiB); your site may have its own. ![Custom compute](/img/screens/wiz-compute-custom.png) @@ -80,7 +80,7 @@ choice. The seeded catalogue runs from **Compute S** (2 vCPU · 4 GiB · 20 GiB) disk up to 500 GB. The sliders stop at what one node can realistically give: asking for more than a node has only puts the session in the queue. -:::tip The scratch disk is not a volume +:::tip[The scratch disk is not a volume] The disk in the preset is the container's own scratch space. It disappears when the session ends. Anything you want to keep belongs on a [volume](./data.md). ::: @@ -132,7 +132,7 @@ Each tile carries its own status: - **Capacity short** / **Unavailable** — no card of this model can serve that tier (for example, no card is configured for exclusive use). -:::tip Take the smallest tier that fits +:::tip[Take the smallest tier that fits] Occupancy is what you pay for, and a slice you do not use is a slice someone else could have. An eighth of a card costs an eighth of the rate. ::: @@ -150,7 +150,7 @@ asking for 14 GB and 5% cores is billed on the VRAM, not the cores. ## Step 3 — Image -![Image catalogue](/img/screens/wiz-step3.png) +![Image catalog](/img/screens/wiz-step3.png) ![Image tiles](/img/screens/wiz-image.png) @@ -166,7 +166,7 @@ The tags on each tile tell you what you are getting: yourself. Images marked **My image** are ones registered for you alone rather than for everyone; see -[Images](../admin/images.md) for how the catalogue is filled. +[Images](../admin/images.md) for how the catalog is filled. --- diff --git a/docs/user/sessions-end.md b/docs/user/sessions-end.md index 722e95a..2a14dea 100644 --- a/docs/user/sessions-end.md +++ b/docs/user/sessions-end.md @@ -37,7 +37,7 @@ billed at all. | The session's record, event log, and bill in your history | The container, its processes, and its connect links | | Volumes themselves, and what they cost (nothing) | The GPU reservation | -:::caution Check your volumes first +:::caution[Check your volumes first] Work saved in the home directory of a JupyterLab session is on the scratch disk, not on a volume, unless you put it there. Copy anything you want to keep to a mounted path before you terminate. diff --git a/docs/user/sessions-manage.md b/docs/user/sessions-manage.md index 26ce280..f1cee7d 100644 --- a/docs/user/sessions-manage.md +++ b/docs/user/sessions-manage.md @@ -33,8 +33,8 @@ untouched, and keeping them costs nothing. cluster is full it waits in the [queue](./sessions-queue.md) and comes up by itself. The session keeps its name, its image, and its mounts. -:::note Idle sessions are paused for you -Your site's policy sets an idle timeout (an hour, in the default catalogue). A GPU session whose +:::note[Idle sessions are paused for you] +Your site's policy sets an idle timeout (an hour, in the default catalog). A GPU session whose card has been doing nothing that long is paused automatically, so a forgotten notebook does not hold a card overnight. Nothing is lost — resume and carry on. ::: diff --git a/docs/user/sessions-queue.md b/docs/user/sessions-queue.md index 7c88f2d..d5f2bed 100644 --- a/docs/user/sessions-queue.md +++ b/docs/user/sessions-queue.md @@ -35,7 +35,7 @@ queued sessions are admitted in **priority order**, and within the same priority they joined. Administrators can raise the priority of an entry; you cannot raise your own. Your [resource policy](../admin/resources.md) also caps how many sessions you may have waiting -at once (two, in the default catalogue). +at once (two, in the default catalog). ## While you wait diff --git a/docs/user/wallet-ledger.md b/docs/user/wallet-ledger.md index ba3ca8f..d841d5d 100644 --- a/docs/user/wallet-ledger.md +++ b/docs/user/wallet-ledger.md @@ -39,7 +39,7 @@ Two tags appear on usage rows: - **billing now** — the session is still running, so this row is not final yet. - **settled** — the session has ended and this row will not change. -A long-running session is summarised rather than written second by second: one row per billing +A long-running session is summarized rather than written second by second: one row per billing period, with the number of underlying entries in its tooltip. ## Finding things diff --git a/frontend/.eslintrc.cjs b/frontend/.eslintrc.cjs deleted file mode 100644 index e7750a1..0000000 --- a/frontend/.eslintrc.cjs +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = { - root: true, - env: { browser: true, es2020: true }, - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/recommended', - 'plugin:react-hooks/recommended', - ], - parser: '@typescript-eslint/parser', - plugins: ['react-refresh'], - ignorePatterns: ['dist', 'src/api/schema.d.ts', '.eslintrc.cjs'], - rules: { - 'react-refresh/only-export-components': 'off', - '@typescript-eslint/no-explicit-any': 'warn', - }, -}; diff --git a/frontend/eslint.config.js b/frontend/eslint.config.js new file mode 100644 index 0000000..1b4aca1 --- /dev/null +++ b/frontend/eslint.config.js @@ -0,0 +1,26 @@ +// ESLint 9+ flat config. Replaces .eslintrc.cjs: same rule set, same ignores, expressed the new way. +import js from '@eslint/js'; +import tseslint from 'typescript-eslint'; +import reactHooks from 'eslint-plugin-react-hooks'; +import reactRefresh from 'eslint-plugin-react-refresh'; +import globals from 'globals'; + +export default tseslint.config( + { ignores: ['dist', 'src/api/schema.d.ts', 'eslint.config.js'] }, + js.configs.recommended, + ...tseslint.configs.recommended, + { + files: ['**/*.{ts,tsx}'], + languageOptions: { ecmaVersion: 2020, globals: globals.browser }, + plugins: { 'react-hooks': reactHooks, 'react-refresh': reactRefresh }, + rules: { + // The two hook rules this project has always enforced. eslint-plugin-react-hooks 7 also + // ships the React Compiler rule set in its recommended config (set-state-in-effect, refs, + // purity, ...); adopting those is a separate, deliberate change, not a dependency bump. + 'react-hooks/rules-of-hooks': 'error', + 'react-hooks/exhaustive-deps': 'warn', + 'react-refresh/only-export-components': 'off', + '@typescript-eslint/no-explicit-any': 'warn', + }, + }, +); diff --git a/frontend/openapi.json b/frontend/openapi.json index 708e403..6f451b5 100644 --- a/frontend/openapi.json +++ b/frontend/openapi.json @@ -1 +1 @@ -{"openapi": "3.1.0", "info": {"title": "gShare API", "version": "v1"}, "paths": {"/api/v1/auth/me": {"get": {"tags": ["users"], "summary": "Auth Me", "description": "Return identity/role/memberships of the current principal.\n\nmemberships is returned as a list of {group_id, project_name, role} for the console's context\nswitcher and RBAC, converted from the internal {project_id: role} mapping with names resolved.", "operationId": "auth_me_api_v1_auth_me_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MeResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/auth/login": {"post": {"tags": ["users"], "summary": "Auth Login", "description": "Email+password local login (gated by AUTH_ALLOW_LOCAL_PASSWORD).\n\nLooks the user up by email and issues an HS256 token signed with USER_JWT_SECRET, which\njwt_auth.verify_jwt verifies.", "operationId": "auth_login_api_v1_auth_login_post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/_LoginRequest"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/auth/signup": {"post": {"tags": ["users"], "summary": "Auth Signup", "description": "Self-service registration, governed by the sign-up policy in system settings.\n\n`closed` refuses outright; `open` creates a usable account; `approval` creates it as\n``pending``, which cannot sign in until an administrator approves it. Either way the account\nstarts with **no department** \u2014 an administrator assigns one at approval, or later. Until then\nthe account resolves to the global resource policy and has no group wallet to draw credits\nfrom, which is why the approval screen assigns a department in the same step.", "operationId": "auth_signup_api_v1_auth_signup_post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/_SignupRequest"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/approve": {"post": {"tags": ["users"], "summary": "Approve User", "description": "Approve a self-registered account: assign the department, activate, grant welcome credit.\n\nOne step rather than three, because a half-approved account (active, no department, no\ncredits) is a state nobody wants to find. super_admin, or an org_admin for a group of theirs.", "operationId": "approve_user_api_v1_users__user_id__approve_post", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserApproveBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/auth/change-password": {"post": {"tags": ["users"], "summary": "Change Password", "description": "Change your own password. Unless must_change_password is set, the current password is\nverified. A fresh token is issued afterwards.", "operationId": "change_password_api_v1_auth_change_password_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChangePasswordRequest"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users": {"get": {"tags": ["users"], "summary": "List Users", "description": "Paginated user list. super_admin, org_admin, or group_admin, the latter two scoped to the\ngroups they administer.", "operationId": "list_users_api_v1_users_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "org_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}}, {"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["users"], "summary": "Create User", "description": "Create a user + enroll them into the chosen group with an initial membership role.\n\nThe new user is created in ``active`` (or ``suspended``) state; ``invited`` is reserved for the\ninvite-mail flow. A group is mandatory \u2014 the user joins it on creation (org is derived from the\ngroup). Email is UNIQUE (-> 409 conflict). super_admin\u00b7org_admin.", "operationId": "create_user_api_v1_users_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/bulk": {"post": {"tags": ["users"], "summary": "Bulk Create Users", "description": "Roster import: create up to 200 users per request, each with a personal wallet, a\nmembership in the chosen group, and a server-generated initial password returned once in the\nresponse (must_change_password forces rotation at first login).\n\nPartial success by design: rows report ``created`` / ``exists`` / ``invalid`` individually so\nre-uploading a roster is safe \u2014 existing accounts are reported, not fatal. The whole batch is\nidempotent on the Idempotency-Key (a replay returns the stored result, passwords included,\nfor 24h). One audit record per batch, not one per student. super_admin\u00b7org_admin.", "operationId": "bulk_create_users_api_v1_users_bulk_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkUserCreate"}}}}, "responses": {"207": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/resolve": {"get": {"tags": ["users"], "summary": "Resolve User", "description": "Resolve an EXACT email to {id, name} for the volume-share confirm step.\n\nAny authenticated user may call it: sharing needs \"does this address exist, and who is it\",\nand members cannot list users. Only an exact match answers \u2014 no enumeration surface beyond\nwhat grant-by-email already reveals.", "operationId": "resolve_user_api_v1_users_resolve_get", "parameters": [{"name": "email", "in": "query", "required": true, "schema": {"type": "string", "minLength": 3, "maxLength": 254, "title": "Email"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}": {"get": {"tags": ["users"], "summary": "Get User", "description": "User detail incl. memberships. self or super_admin/org_admin.", "operationId": "get_user_api_v1_users__user_id__get", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["users"], "summary": "Update User", "description": "Update a user. What may be changed depends on the caller's role.\n\n- super_admin: email, name, status, and password reset. Group membership has its own endpoint.\n- org_admin: password reset (and group) for users in their organization. Not email or name.\n- group_admin: password reset only, for users in their group.\n- The user themselves: their display name only.", "operationId": "update_user_api_v1_users__user_id__patch", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Delete User", "description": "Deactivate (soft, default) or hard-delete a user.\n\nDefault = soft delete (``status=suspended`` + ``deleted_at``). ``?hard=true`` is\nsuper_admin-only and refused when a live session exists (ledger preservation -> 409 conflict).", "operationId": "delete_user_api_v1_users__user_id__delete", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "hard", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Hard"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/usage": {"get": {"tags": ["users"], "summary": "Get User Usage", "description": "Live resource footprint: sessions, host compute, GPU slices, volumes, wallet.\n\nSelf or an administrator (``user.read``). Everything is CURRENT state, not history \u2014 the\nadmin drawer answers \"what is this user holding right now?\".", "operationId": "get_user_usage_api_v1_users__user_id__usage_get", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/department": {"put": {"tags": ["users"], "summary": "Set User Department", "description": "Set, or move, a user's group. super_admin or org_admin.\n\n- super_admin: move to any group, or pass None to remove all group membership.\n- org_admin: move only within their own organization; memberships elsewhere are left alone.\n\nIf the user is not already in the target group they are added as a member, and their previous\ngroup memberships within the caller's scope are removed.", "operationId": "set_user_department_api_v1_users__user_id__department_put", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserDepartmentSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/global-role": {"put": {"tags": ["users"], "summary": "Set Global Role", "description": "Grant or revoke global roles; super_admin only. Several roles may be granted at once.", "operationId": "set_global_role_api_v1_users__user_id__global_role_put", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GlobalRoleSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations": {"get": {"tags": ["groups"], "summary": "List Organizations", "description": "List organizations. super_admin sees all; org_admin sees only their own (tenant\nisolation).", "operationId": "list_organizations_api_v1_organizations_get", "parameters": [{"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Create Organization", "description": "Create an organization. super_admin only.", "operationId": "create_organization_api_v1_organizations_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OrgCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations/{org_id}": {"get": {"tags": ["groups"], "summary": "Get Organization", "description": "Fetch one organization, for deep links from the edit and admin pages.", "operationId": "get_organization_api_v1_organizations__org_id__get", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["groups"], "summary": "Update Organization", "description": "Update an organization's name or status. super_admin only.", "operationId": "update_organization_api_v1_organizations__org_id__patch", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OrgUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["groups"], "summary": "Delete Organization", "description": "Soft-delete an organization. super_admin only; 409 while live groups remain, to avoid\norphans.", "operationId": "delete_organization_api_v1_organizations__org_id__delete", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations/{org_id}/admins": {"get": {"tags": ["groups"], "summary": "List Org Admins", "description": "List an organization's admins. super_admin, or an org_admin of that organization.", "operationId": "list_org_admins_api_v1_organizations__org_id__admins_get", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Add Org Admin", "description": "Appoint an organization admin. super_admin only.", "operationId": "add_org_admin_api_v1_organizations__org_id__admins_post", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OrgAdminCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations/{org_id}/admins/{user_id}": {"delete": {"tags": ["groups"], "summary": "Remove Org Admin", "description": "Remove an organization admin. super_admin only.", "operationId": "remove_org_admin_api_v1_organizations__org_id__admins__user_id__delete", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects": {"get": {"tags": ["groups"], "summary": "List Projects", "description": "List groups. super_admin sees all; everyone else sees only the groups they belong to.", "operationId": "list_projects_api_v1_projects_get", "parameters": [{"name": "org_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Create Project", "description": "Create a group along with its default wallet. super_admin or org_admin.", "operationId": "create_project_api_v1_projects_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjectCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects/{group_id}": {"get": {"tags": ["groups"], "summary": "Get Project", "description": "Fetch one group, for deep links from the edit, admin, and delete pages.", "operationId": "get_project_api_v1_projects__group_id__get", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["groups"], "summary": "Update Project", "description": "Update a group's name or archived status. super_admin or group_admin.", "operationId": "update_project_api_v1_projects__group_id__patch", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjectPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["groups"], "summary": "Delete Project", "description": "Soft-delete a group. super_admin or org_admin; 409 while live sessions remain.\n\nMemberships are removed with it, so a soft-deleted group leaves no permissions behind. The\ngroup wallet is preserved.", "operationId": "delete_project_api_v1_projects__group_id__delete", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects/{group_id}/memberships": {"get": {"tags": ["groups"], "summary": "List Memberships", "description": "List a group's memberships. super_admin or group_admin.", "operationId": "list_memberships_api_v1_projects__group_id__memberships_get", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Add Membership", "description": "Add a member or grant a role. A guest must carry expires_at. super_admin or group_admin.", "operationId": "add_membership_api_v1_projects__group_id__memberships_post", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MembershipCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects/{group_id}/memberships/{membership_id}": {"patch": {"tags": ["groups"], "summary": "Update Membership", "description": "Change a member's role. Demoting the last admin returns 409. super_admin or group_admin.", "operationId": "update_membership_api_v1_projects__group_id__memberships__membership_id__patch", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "membership_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Membership Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MembershipPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["groups"], "summary": "Remove Membership", "description": "Remove a member. Removing the last admin returns 409. super_admin or group_admin.", "operationId": "remove_membership_api_v1_projects__group_id__memberships__membership_id__delete", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "membership_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Membership Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets": {"get": {"tags": ["credits"], "summary": "List Wallets", "operationId": "list_wallets_api_v1_credits_wallets_get", "parameters": [{"name": "owner_type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Type"}}, {"name": "owner_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/WalletRead"}, "title": "Response List Wallets Api V1 Credits Wallets Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/me": {"get": {"tags": ["credits"], "summary": "My Wallet", "operationId": "my_wallet_api_v1_credits_wallets_me_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WalletRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}": {"get": {"tags": ["credits"], "summary": "Get Wallet", "operationId": "get_wallet_api_v1_credits_wallets__wallet_id__get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WalletRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/topup": {"post": {"tags": ["credits"], "summary": "Topup", "operationId": "topup_api_v1_credits_wallets__wallet_id__topup_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRequestBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/adjust": {"post": {"tags": ["credits"], "summary": "Adjust", "operationId": "adjust_api_v1_credits_wallets__wallet_id__adjust_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AdjustBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/transfer": {"post": {"tags": ["credits"], "summary": "Transfer", "operationId": "transfer_api_v1_credits_wallets__wallet_id__transfer_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TransferBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-scope": {"get": {"tags": ["credits"], "summary": "Allocation Scope", "description": "Return the pools the caller can allocate from, and each pool's targets, with names.\n\nAn org_admin gets their organization's wallet, whose children are that organization's groups; a\ngroup_admin gets their group's wallet, whose children are its members; a super_admin gets\neverything. The UI uses this to pick a pool, populate its targets, and toggle direction between\nallocate and reclaim.", "operationId": "allocation_scope_api_v1_credits_allocation_scope_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/refill-schedule": {"get": {"tags": ["credits"], "summary": "Get Refill Schedule", "description": "When the monthly refill fires: day-of-month and hour (KST). Defaults: day 1, 00:00.", "operationId": "get_refill_schedule_api_v1_credits_refill_schedule_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["credits"], "summary": "Set Refill Schedule", "description": "Set the refill day/hour. super_admin \u2014 the same authority that sets the monthly total.", "operationId": "set_refill_schedule_api_v1_credits_refill_schedule_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RefillScheduleBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocate": {"post": {"tags": ["credits"], "summary": "Allocate", "description": "Allocate credits down the hierarchy (organization -> project -> user), or reclaim upwards.\nAn idempotency key is required.\n\n\"Within your allowance\" is enforced automatically by the source wallet's available balance, and\nexceeding it returns 402. Authorization is handled by _assert_can_allocate.", "operationId": "allocate_api_v1_credits_allocate_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AllocateBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/monthly-grant": {"post": {"tags": ["credits"], "summary": "Set Monthly Grant", "description": "Set a child wallet's monthly automatic refill, as the administrator one level up.\n\nThe siblings' grants must sum within the parent's grant; 0 disables refills for that wallet. The\nrefill itself \u2014 topping the balance up to the grant at the start of each month, never taking\na surplus away \u2014 is performed by the credit_refill worker.", "operationId": "set_monthly_grant_api_v1_credits_wallets__wallet_id__monthly_grant_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonthlyGrantBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WalletRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/bulk-allocate": {"post": {"tags": ["credits"], "summary": "Bulk Allocate", "description": "Allocate ``amount`` from the group's wallet to EVERY member's personal wallet at once.\n\nThe source balance is checked up front against n\u00d7amount (402 on shortfall \u2014 all or nothing,\nno partially funded cohort), and every per-wallet transaction carries an idempotency key\nderived from the batch key, so a replay after a crash completes exactly once per member.\ngroup_admin and above.", "operationId": "bulk_allocate_api_v1_credits_bulk_allocate_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkAllocateBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/bulk-monthly-grant": {"post": {"tags": ["credits"], "summary": "Bulk Monthly Grant", "description": "Set the same monthly refill on every member wallet of the group.\n\nThe ceiling check runs once for the whole cohort: n\u00d7amount must stay within the group\nwallet's own monthly grant (the same sibling-sum invariant set_monthly_grant enforces\nper wallet, without the O(n\u00b2) of calling it n times). Increases credit immediately, like\nthe single-wallet endpoint. group_admin and above.", "operationId": "bulk_monthly_grant_api_v1_credits_bulk_monthly_grant_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkMonthlyGrantBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-requests": {"post": {"tags": ["credits"], "summary": "Create Allocation Request", "description": "Create a credit allocation request, routed one level up: a user's goes to the group admin, a\ngroup's to the organization admin, an organization's to a super_admin.", "operationId": "create_allocation_request_api_v1_credits_allocation_requests_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AllocationRequestCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["credits"], "summary": "List Allocation Requests", "description": "box=mine lists the requests you raised; box=incoming lists pending requests you can\napprove; box=handled lists the decided ones from the same inbox \u2014 the approver's history.", "operationId": "list_allocation_requests_api_v1_credits_allocation_requests_get", "parameters": [{"name": "box", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(incoming|mine|handled)$", "default": "incoming", "title": "Box"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-requests/{request_id}/approve": {"post": {"tags": ["credits"], "summary": "Approve Allocation Request", "description": "Approve a request: allocate from the parent wallet to the target, or top the target up when\nthe parent is the system wallet. An insufficient pool returns 409, prompting escalation.", "operationId": "approve_allocation_request_api_v1_credits_allocation_requests__request_id__approve_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-requests/{request_id}/reject": {"post": {"tags": ["credits"], "summary": "Reject Allocation Request", "operationId": "reject_allocation_request_api_v1_credits_allocation_requests__request_id__reject_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AllocationRejectBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/spend-daily": {"get": {"tags": ["credits"], "summary": "Spend Daily", "description": "Daily spend (consume + storage) over [from, to], for the wallet's usage chart.\n\nAggregation happens here rather than over the paged ledger: a chart drawn from page one of the\ntransactions would silently truncate. Buckets follow the caller's clock via tz_offset_min\n(KST = +540), since \"a day\" on the chart is the user's day, not UTC's. Aggregated in Python so\nthe same query runs on Postgres and the SQLite test harness; the range is capped to a year.", "operationId": "spend_daily_api_v1_credits_wallets__wallet_id__spend_daily_get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "from", "in": "query", "required": true, "schema": {"type": "string", "format": "date", "title": "From"}}, {"name": "to", "in": "query", "required": true, "schema": {"type": "string", "format": "date", "title": "To"}}, {"name": "tz_offset_min", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 840, "minimum": -840, "default": 0, "title": "Tz Offset Min"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/SpendDayRead"}, "title": "Response Spend Daily Api V1 Credits Wallets Wallet Id Spend Daily Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/transactions": {"get": {"tags": ["credits"], "summary": "Transactions", "description": "The wallet ledger.\n\ngroup=\"session\" rolls the per-minute consume rows of one session into a single line (period,\ntotal, entry count); every other transaction type is a discrete event and passes through\nuntouched. Grouping happens in SQL because a long session produces hundreds of rows: folding\nthem client-side would only fold whatever landed on the current page.", "operationId": "transactions_api_v1_credits_wallets__wallet_id__transactions_get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "group", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(none|session)$", "default": "none", "title": "Group"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/TransactionRead"}, "title": "Response Transactions Api V1 Credits Wallets Wallet Id Transactions Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/holds": {"get": {"tags": ["credits"], "summary": "Holds", "description": "Active reservations + per-session settle status.\n\nReconstructed from the ledger: hold/consume/settle/refund txns are grouped by ``ref``\n(session id). A session with a hold but no settle is ``active``; otherwise ``settled``.", "operationId": "holds_api_v1_credits_wallets__wallet_id__holds_get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/topup-requests": {"post": {"tags": ["credits"], "summary": "Create Topup Request", "operationId": "create_topup_request_api_v1_credits_topup_requests_post", "parameters": [{"name": "wallet_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRequestBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["credits"], "summary": "List Topup Requests", "operationId": "list_topup_requests_api_v1_credits_topup_requests_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "wallet_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Id"}}, {"name": "scope", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(mine|all)$", "default": "mine", "title": "Scope"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRequestListResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/topup-requests/{request_id}/approve": {"post": {"tags": ["credits"], "summary": "Approve Topup Request", "operationId": "approve_topup_request_api_v1_credits_topup_requests__request_id__approve_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/topup-requests/{request_id}/reject": {"post": {"tags": ["credits"], "summary": "Reject Topup Request", "operationId": "reject_topup_request_api_v1_credits_topup_requests__request_id__reject_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRejectBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/budgets": {"get": {"tags": ["budgets"], "summary": "List Budgets", "operationId": "list_budgets_api_v1_budgets_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "action", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/BudgetRead"}, "title": "Response List Budgets Api V1 Budgets Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["budgets"], "summary": "Create Budget", "operationId": "create_budget_api_v1_budgets_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/budgets/{budget_id}": {"get": {"tags": ["budgets"], "summary": "Get Budget", "operationId": "get_budget_api_v1_budgets__budget_id__get", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["budgets"], "summary": "Update Budget", "operationId": "update_budget_api_v1_budgets__budget_id__patch", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["budgets"], "summary": "Delete Budget", "operationId": "delete_budget_api_v1_budgets__budget_id__delete", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/budgets/{budget_id}/forecast": {"get": {"tags": ["budgets"], "summary": "Forecast", "description": "Project depletion from recent burn rate.\n\nburn_rate_per_day = consume over the lookback window / lookback days.\nprojected_depletion_at = now + remaining_credit / burn_rate_per_day.", "operationId": "forecast_api_v1_budgets__budget_id__forecast_get", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "lookback", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(7d|14d|30d)$", "default": "7d", "title": "Lookback"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetForecast"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/offerings": {"get": {"tags": ["offerings"], "summary": "List Offerings", "description": "Catalog list. Authenticated-but-open read; no admin gate.\n\nRetired (status=inactive) offerings are hidden from non-admins; administrators still see\nthem so they can reactivate or audit pricing.", "operationId": "list_offerings_api_v1_offerings_get", "parameters": [{"name": "gpu_model", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}}, {"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "default": "credit_per_hour", "title": "Sort"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["offerings"], "summary": "Create Offering", "operationId": "create_offering_api_v1_offerings_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OfferingCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/offerings/{offering_id}": {"get": {"tags": ["offerings"], "summary": "Get Offering", "description": "Fetch one offering, for deep links from the edit page. Readable by any authenticated\ncaller.", "operationId": "get_offering_api_v1_offerings__offering_id__get", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["offerings"], "summary": "Update Offering", "description": "Update offering; appends to price history on credit_per_hour change.", "operationId": "update_offering_api_v1_offerings__offering_id__patch", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OfferingUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["offerings"], "summary": "Delete Offering", "description": "Delete an offering; super_admin only. Rejected while a session still references it \u2014\ndeactivate it instead.", "operationId": "delete_offering_api_v1_offerings__offering_id__delete", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/offerings/{offering_id}/price-history": {"get": {"tags": ["offerings"], "summary": "Price History", "operationId": "price_history_api_v1_offerings__offering_id__price_history_get", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "from", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "From"}}, {"name": "to", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "To"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-presets": {"get": {"tags": ["presets"], "summary": "List Presets", "operationId": "list_presets_api_v1_resource_presets_get", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "kind", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Kind"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["presets"], "summary": "Create Preset", "operationId": "create_preset_api_v1_resource_presets_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PresetCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-presets/{preset_id}": {"get": {"tags": ["presets"], "summary": "Get Preset", "description": "Fetch one preset, for deep links from the edit page.", "operationId": "get_preset_api_v1_resource_presets__preset_id__get", "parameters": [{"name": "preset_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Preset Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["presets"], "summary": "Update Preset", "description": "Update a preset; super_admin only. kind is immutable, and only the fields belonging to that\nkind are applied.", "operationId": "update_preset_api_v1_resource_presets__preset_id__patch", "parameters": [{"name": "preset_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Preset Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PresetUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["presets"], "summary": "Delete Preset", "description": "Delete a preset. Same authority as preset.create: super_admin.", "operationId": "delete_preset_api_v1_resource_presets__preset_id__delete", "parameters": [{"name": "preset_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Preset Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/effective": {"get": {"tags": ["policies"], "summary": "Effective Policy", "description": "The effective policy for the caller, with current usage and headroom, so the session wizard\ncan show the limits.\n\nResolution is the per-field merge in app.domain.policy (user \u2192 group \u2192 org \u2192 global), the\nsame module the admission gate uses. Caps are per user, so usage sums over the CALLER's\nactive sessions regardless of group.", "operationId": "effective_policy_api_v1_resource_policies_effective_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies": {"get": {"tags": ["policies"], "summary": "List Policies", "operationId": "list_policies_api_v1_resource_policies_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["policies"], "summary": "Create Policy", "operationId": "create_policy_api_v1_resource_policies_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PolicyCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/requests": {"post": {"tags": ["policies"], "summary": "Create Resource Request", "description": "Ask for a bigger compute quota. At least one target, all positive; note required.", "operationId": "create_resource_request_api_v1_resource_policies_requests_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ResourceRequestCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["policies"], "summary": "List Resource Requests", "operationId": "list_resource_requests_api_v1_resource_policies_requests_get", "parameters": [{"name": "box", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(mine|incoming)$", "default": "mine", "title": "Box"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/requests/{request_id}/approve": {"post": {"tags": ["policies"], "summary": "Approve Resource Request", "description": "Approve: upsert the requester's USER-scope policy with ONLY the granted limit keys.\n\nEverything not granted stays inherited (per-field most-specific merge), so the group/global\ndefaults remain the single source for the rest of the policy.", "operationId": "approve_resource_request_api_v1_resource_policies_requests__request_id__approve_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/requests/{request_id}/reject": {"post": {"tags": ["policies"], "summary": "Reject Resource Request", "operationId": "reject_resource_request_api_v1_resource_policies_requests__request_id__reject_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_RRReject"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/{policy_id}": {"get": {"tags": ["policies"], "summary": "Get Policy", "description": "Fetch one policy, for deep links from the edit page.", "operationId": "get_policy_api_v1_resource_policies__policy_id__get", "parameters": [{"name": "policy_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Policy Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["policies"], "summary": "Update Policy", "operationId": "update_policy_api_v1_resource_policies__policy_id__patch", "parameters": [{"name": "policy_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Policy Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PolicyUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["policies"], "summary": "Delete Policy", "description": "Delete a resource policy. The global policy is super_admin only; the rest follow\npolicy.delete, which admits super_admin, org_admin, and group_admin.", "operationId": "delete_policy_api_v1_resource_policies__policy_id__delete", "parameters": [{"name": "policy_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Policy Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/preview-cost": {"post": {"tags": ["sessions"], "summary": "Preview Cost", "description": "Estimate cost without creating a session (pricing.estimate).\n\nestimated_credit_per_hour = offering.credit_per_hour * occupancy;\noccupancy = max(gpu_mem_mb/device_total_mem_mb, gpu_cores/100);\nhold_amount = estimated_credit_per_hour \u2014 admission reserves one hour up front.\nCPU (free) sessions are always 0.", "operationId": "preview_cost_api_v1_sessions_preview_cost_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PreviewCostRequest"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PreviewCostResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions": {"post": {"tags": ["sessions"], "summary": "Create Session", "description": "Admit a session through the scheduler gate. Idempotency-Key required.", "operationId": "create_session_api_v1_sessions_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["sessions"], "summary": "List Sessions", "description": "List sessions, newest first, paginated.\n\nscope=\"mine\" (the default, backing the user's Sessions page) returns **only the caller's own\nsessions**, whatever their role. Administrators do not see other people's sessions on their\npersonal screen; that is what scope=all is for. scope=\"all\" (the administrators' session\nmonitoring screen) returns everything within the caller's authority: super_admin and org_admin\nsee all sessions, group_admin sees their own plus those of the groups they administer. A plain\nuser asking for scope=all is silently downgraded to their own sessions, so it cannot be used to\nescalate.", "operationId": "list_sessions_api_v1_sessions_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "scope", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(mine|all)$", "default": "mine", "title": "Scope"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/events": {"get": {"tags": ["sessions"], "summary": "Sessions Monitor Events", "description": "Admin session/queue monitor SSE stream.\n\nNOTE: this literal route MUST be declared before ``/sessions/{session_id}`` \u2014 otherwise the\nparameterized route captures ``/sessions/events`` (session_id=\"events\") and returns 404.", "operationId": "sessions_monitor_events_api_v1_sessions_events_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/gpu-availability": {"get": {"tags": ["sessions"], "summary": "Gpu Availability", "description": "Free GPU capacity per model, used by the session wizard to disable tiers. member and above.\n\nGroups the currently ready devices by model and returns each device's free memory, free cores,\nand mode. The console uses this to disable tiers that would not fit on a single card of the\nselected model, since the scheduler requires a fit on one device.\n\nThis is a literal path, so it must be declared before ``/sessions/{session_id}`` \u2014 the same\nreason the events route is.", "operationId": "gpu_availability_api_v1_sessions_gpu_availability_get", "parameters": [{"name": "fleet", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Fleet"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}": {"get": {"tags": ["sessions"], "summary": "Get Session", "description": "Fetch a single session (owner\u00b7admin).", "operationId": "get_session_api_v1_sessions__session_id__get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["sessions"], "summary": "Terminate Session", "description": "Terminate + settle.", "operationId": "terminate_session_api_v1_sessions__session_id__delete", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/start": {"post": {"tags": ["sessions"], "summary": "Start Session", "description": "Resume billing state machine.", "operationId": "start_session_api_v1_sessions__session_id__start_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/stop": {"post": {"tags": ["sessions"], "summary": "Stop Session", "description": "Stop (pause billing) + finalize remaining consume.", "operationId": "stop_session_api_v1_sessions__session_id__stop_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/restart": {"post": {"tags": ["sessions"], "summary": "Restart Session", "description": "Restart a session.", "operationId": "restart_session_api_v1_sessions__session_id__restart_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/force-terminate": {"post": {"tags": ["sessions"], "summary": "Force Terminate", "description": "Admin force-terminate without owner consent. The free-text reason lands in the audit log;\nthe session's status_reason stays the typed `admin_stopped` the console maps to a message.", "operationId": "force_terminate_api_v1_sessions__session_id__force_terminate_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"$ref": "#/components/schemas/ForceTerminateBody"}, {"type": "null"}], "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/bulk-terminate": {"post": {"tags": ["sessions"], "summary": "Bulk Terminate", "description": "Force-terminate multiple sessions; per-target result array, idempotent.", "operationId": "bulk_terminate_api_v1_sessions_bulk_terminate_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkTerminateRequest"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/logs": {"get": {"tags": ["sessions"], "summary": "Session Logs", "description": "NOT IMPLEMENTED: nothing streams pod logs into this plane (the operator has no Redis\nproducer), so this always returned an empty list dressed up as a log. Honest 501 until a log\npipeline exists \u2014 use `kubectl logs` on the session pod meanwhile.", "operationId": "session_logs_api_v1_sessions__session_id__logs_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "tail", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 5000, "minimum": 1, "default": 200, "title": "Tail"}}, {"name": "stream", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(stdout|stderr|all)$", "default": "all", "title": "Stream"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/connections": {"get": {"tags": ["sessions"], "summary": "Session Connections", "description": "Issue one-time cnx_ connection tokens; `kind` narrows to one app (one token minted).", "operationId": "session_connections_api_v1_sessions__session_id__connections_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "kind", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "pattern": "^(vscode|jupyter|terminal)$"}, {"type": "null"}], "title": "Kind"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ConnectionInfo"}, "title": "Response Session Connections Api V1 Sessions Session Id Connections Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/usage": {"get": {"tags": ["sessions"], "summary": "Session Usage Self", "description": "Measured live usage of the session's pod (owner\u00b7admin) \u2014 the detail page's meters.", "operationId": "session_usage_self_api_v1_sessions__session_id__usage_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/usage/live": {"get": {"tags": ["sessions"], "summary": "Session Usage Live", "description": "The last few minutes of one-second samples from the node agent (owner\u00b7admin).\n\nThis is the live view. It is deliberately separate from the Prometheus-backed series: that one\nis the record and covers GPU and history, this one answers \"is it running yet\" without waiting\nfor a scrape. `live` says whether an agent is actually reporting, so the console can show the\nslower series instead of a stale line when the DaemonSet is not deployed.", "operationId": "session_usage_live_api_v1_sessions__session_id__usage_live_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/usage/timeseries": {"get": {"tags": ["sessions"], "summary": "Session Usage Series Self", "description": "The usage metrics over a range (owner\u00b7admin) \u2014 the detail page's sparklines.", "operationId": "session_usage_series_self_api_v1_sessions__session_id__usage_timeseries_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "default": "15m", "title": "Range"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/timeline": {"get": {"tags": ["sessions"], "summary": "Session Timeline", "description": "Lifecycle timeline for the detail screen: created \u2192 queued/preparing \u2192 running \u2192 \u2026 with\nreasons, so an error state is readable from the log instead of a separate message box.", "operationId": "session_timeline_api_v1_sessions__session_id__timeline_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/checkpoints": {"post": {"tags": ["sessions"], "summary": "Create Checkpoint", "description": "NOT IMPLEMENTED: no worker or operator path takes a checkpoint yet \u2014 a row here would be\nan empty promise (storage_ref stays NULL forever). Honest 501 until the pipeline exists.", "operationId": "create_checkpoint_api_v1_sessions__session_id__checkpoints_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["sessions"], "summary": "List Checkpoints", "description": "List checkpoints for a session, newest first.", "operationId": "list_checkpoints_api_v1_sessions__session_id__checkpoints_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/checkpoints/{checkpoint_id}/restore": {"post": {"tags": ["sessions"], "summary": "Restore Checkpoint", "description": "NOT IMPLEMENTED: restore has no execution path (the operator's checkpointer states restore\nis intentionally unimplemented) \u2014 returning \"restoring\" here was a fabrication. Honest 501.", "operationId": "restore_checkpoint_api_v1_sessions__session_id__checkpoints__checkpoint_id__restore_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "checkpoint_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Checkpoint Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/events": {"get": {"tags": ["sessions"], "summary": "Session Events", "description": "Per-session SSE event stream.\n\nSubscribes to the session's status-change channel (Redis pub/sub fed by status_sync) and pushes\nstatus_changed / phase / allocation / heartbeat events. 404/403 are raised before the stream is\nestablished; the stream terminates cleanly on client disconnect.\n\nThe access check opens its own short-lived DB session: a Depends(get_db) session would stay\nchecked out of the pool for the whole stream (see get_sse_principal).", "operationId": "session_events_api_v1_sessions__session_id__events_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/queue": {"get": {"tags": ["queue"], "summary": "List Queue", "operationId": "list_queue_api_v1_queue_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/queue/mine": {"get": {"tags": ["queue"], "summary": "My Queue", "operationId": "my_queue_api_v1_queue_mine_get", "parameters": [{"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMineList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/queue/{queue_entry_id}": {"delete": {"tags": ["queue"], "summary": "Cancel Queue Entry", "description": "Cancel a queued entry; the session goes terminated and its hold is released.", "operationId": "cancel_queue_entry_api_v1_queue__queue_entry_id__delete", "parameters": [{"name": "queue_entry_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Queue Entry Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["queue"], "summary": "Update Priority", "description": "Admin reorders the queue: QueueEntry.priority sets the priority band.", "operationId": "update_priority_api_v1_queue__queue_entry_id__patch", "parameters": [{"name": "queue_entry_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Queue Entry Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueuePriorityPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes": {"get": {"tags": ["volumes"], "summary": "List Volumes", "description": "List volumes with scope/type/access_mode filters + pagination.\n\nDefault view is the caller's own world for every role \u2014 the user console must show a\nsuper_admin their volumes, not everyone's. `?all=true` (super_admin only) lists the fleet\nfor the admin volume page.", "operationId": "list_volumes_api_v1_storage_volumes_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}}, {"name": "access_mode", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Access Mode"}}, {"name": "all", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "All"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/VolumeRead"}, "title": "Response List Volumes Api V1 Storage Volumes Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["volumes"], "summary": "Create Volume", "description": "Create a named volume of any type.\n\nEvery type \u2014 personal workspace, group share, dataset, scratch \u2014 can be created as often as\nneeded and attached to sessions. There is no auto-provisioned singleton. Within a scope, the\n(type, name) pair is unique.", "operationId": "create_volume_api_v1_storage_volumes_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/quota-usage": {"get": {"tags": ["volumes"], "summary": "Storage Quota Usage", "description": "Per-scope storage limit, usage, and headroom, for the limit warning on the new-volume form.\n\nReads the same (scope, scope_id) policy and volume quota sum that _assert_storage_quota uses at\ncreation time. has_limit=false means unlimited: no policy, or a limit of 0.\n\nThe scope must be one the caller could create a volume in or belongs to: their own user scope,\na group they are a member of, or the global scope. Another tenant's limit and provisioned total\nare not theirs to read.", "operationId": "storage_quota_usage_api_v1_storage_volumes_quota_usage_get", "parameters": [{"name": "scope", "in": "query", "required": true, "schema": {"type": "string", "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": true, "schema": {"type": "string", "title": "Scope Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}": {"get": {"tags": ["volumes"], "summary": "Get Volume", "description": "Volume detail.", "operationId": "get_volume_api_v1_storage_volumes__volume_id__get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["volumes"], "summary": "Update Volume", "description": "Update volume meta: quota_gb / access_mode / mount_locked.\n\nThe quota only grows. Kubernetes never shrinks a claim, so a smaller ledger figure would free\npolicy headroom against space the pool still physically holds (100 GB \"shrunk\" to 10 GB plus a\nnew 90 GB volume = 190 GB on disk). An increase is bounded by the scope's storage policy \u2014\nvolumes are governed by the policy limit alone, not billed.", "operationId": "update_volume_api_v1_storage_volumes__volume_id__patch", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumePatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["volumes"], "summary": "Delete Volume", "description": "Permanently delete a volume; requires confirm==volume_id, rejects if mounted.\n\n``force`` (system administrator only) terminates every active session still mounting the\nvolume and then deletes it \u2014 the answer to a mount that keeps a shared volume alive against\nits owner's will. The audit row names the sessions that were cut off.", "operationId": "delete_volume_api_v1_storage_volumes__volume_id__delete", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "confirm", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Confirm"}}, {"name": "force", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Force"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/folders": {"get": {"tags": ["volumes"], "summary": "List Folders", "description": "List folders of a volume.", "operationId": "list_folders_api_v1_storage_volumes__volume_id__folders_get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["volumes"], "summary": "Create Folder", "description": "Create a folder (absolute path) under a volume.", "operationId": "create_folder_api_v1_storage_volumes__volume_id__folders_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Body"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/permissions": {"get": {"tags": ["volumes"], "summary": "List Permissions", "description": "List volume share permissions with user names.", "operationId": "list_permissions_api_v1_storage_volumes__volume_id__permissions_get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["volumes"], "summary": "Grant Permission", "description": "Grant/update a volume share permission; upsert on UNIQUE(volume_id,user_id).", "operationId": "grant_permission_api_v1_storage_volumes__volume_id__permissions_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PermissionBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/permissions/{user_id}": {"delete": {"tags": ["volumes"], "summary": "Revoke Permission", "description": "Revoke a share permission; refuse to remove the last owner.\n\nRemoving YOURSELF (leaving a share) is always allowed \u2014 a recipient's \"delete\" is an\nunshare, never a deletion of the original volume. Removing anyone else needs manage rights.", "operationId": "revoke_permission_api_v1_storage_volumes__volume_id__permissions__user_id__delete", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/snapshots": {"post": {"tags": ["volumes"], "summary": "Create Snapshot", "description": "NOT IMPLEMENTED: there is no CSI/storage integration behind snapshots \u2014 rows were being\nauto-flipped to ready by a timer without any data being copied. Honest 501 until a real\nsnapshot backend exists (blocked on the storage-backend decision).", "operationId": "create_snapshot_api_v1_storage_volumes__volume_id__snapshots_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"type": "object", "additionalProperties": true}, {"type": "null"}], "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["volumes"], "summary": "List Snapshots", "description": "List snapshots of a volume.", "operationId": "list_snapshots_api_v1_storage_volumes__volume_id__snapshots_get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/snapshots/{snapshot_id}/restore": {"post": {"tags": ["volumes"], "summary": "Restore Snapshot", "description": "NOT IMPLEMENTED: restore performed no data operation (audit row + fabricated \"restoring\").\nHonest 501 until a real snapshot backend exists.", "operationId": "restore_snapshot_api_v1_storage_volumes__volume_id__snapshots__snapshot_id__restore_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "snapshot_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Snapshot Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"type": "object", "additionalProperties": true}, {"type": "null"}], "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/snapshots/{snapshot_id}": {"delete": {"tags": ["volumes"], "summary": "Delete Snapshot", "description": "Delete a snapshot; reject while still creating.", "operationId": "delete_snapshot_api_v1_storage_volumes__volume_id__snapshots__snapshot_id__delete", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "snapshot_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Snapshot Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/pools": {"get": {"tags": ["storage"], "summary": "List Pools", "description": "Every registered pool; `cluster_id` narrows to the ones that cluster may use.", "operationId": "list_pools_api_v1_storage_pools_get", "parameters": [{"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["storage"], "summary": "Create Pool", "description": "Register a pool. Capacity is left empty: the operator's next tick measures it.", "operationId": "create_pool_api_v1_storage_pools_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/app__api__storage_pools_router__PoolCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/pools/{pool_id}": {"patch": {"tags": ["storage"], "summary": "Update Pool", "operationId": "update_pool_api_v1_storage_pools__pool_id__patch", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["storage"], "summary": "Delete Pool", "description": "Deregister a pool. Nothing on the storage server is touched \u2014 this only stops gShare\ncounting it; the volumes already on it keep working through their StorageClass.", "operationId": "delete_pool_api_v1_storage_pools__pool_id__delete", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters/summary": {"get": {"tags": ["clusters"], "summary": "Cluster Summary", "description": "The clusters a signed-in user can name: id, name and status only. The console's cluster\nselector (hidden while there is one) and the session wizard's cluster choice read this; the\nfull list with kubeconfig references stays super_admin-only.", "operationId": "cluster_summary_api_v1_clusters_summary_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters": {"get": {"tags": ["clusters"], "summary": "List Clusters", "description": "Cluster list. super_admin only.", "operationId": "list_clusters_api_v1_clusters_get", "parameters": [{"name": "role", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}}, {"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["clusters"], "summary": "Register Cluster", "description": "Register a cluster: validate kubeconfig, store secret ref, seed inventory.", "operationId": "register_cluster_api_v1_clusters_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterRegister"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters/{cluster_id}": {"get": {"tags": ["clusters"], "summary": "Get Cluster", "description": "Cluster detail + node/device summary. super_admin only.", "operationId": "get_cluster_api_v1_clusters__cluster_id__get", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["clusters"], "summary": "Update Cluster", "description": "Update name/role only. kubeconfig rotation is out of scope here. super_admin only.", "operationId": "update_cluster_api_v1_clusters__cluster_id__patch", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["clusters"], "summary": "Deregister Cluster", "description": "Deregister a cluster + discard its kubeconfig secret ref.\n\nRefused while live sessions/allocations exist on the cluster (-> 409). super_admin only.", "operationId": "deregister_cluster_api_v1_clusters__cluster_id__delete", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters/{cluster_id}/connection-test": {"post": {"tags": ["clusters"], "summary": "Connection Test", "description": "Re-validate connectivity/health to the cluster apiserver.\n\nRe-runs the runtime/connectivity probe, applies the state-machine transition, and persists the\nnew ``status``. super_admin only.", "operationId": "connection_test_api_v1_clusters__cluster_id__connection_test_post", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/images": {"get": {"tags": ["images"], "summary": "List Images", "description": "List images/templates/ISOs with optional kind/q/tag/public filters. any authenticated.\n\n``public=true`` is what the session wizard uses, listing public images only. The administrative\ncatalogue passes no filter and sees both public and private images.", "operationId": "list_images_api_v1_images_get", "parameters": [{"name": "kind", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Kind"}}, {"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "tag", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Tag"}}, {"name": "public", "in": "query", "required": false, "schema": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Public"}}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Mine"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["images"], "summary": "Create Image", "description": "Register a catalog image referencing an existing registry path. super_admin\u00b7org_admin.", "operationId": "create_image_api_v1_images_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/images/{image_id}": {"get": {"tags": ["images"], "summary": "Get Image", "description": "Image detail. any authenticated, for the shared catalogue and one's own images; another\nuser's private image answers 404 so its existence is not confirmed either.", "operationId": "get_image_api_v1_images__image_id__get", "parameters": [{"name": "image_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Image Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["images"], "summary": "Update Image", "description": "Update image metadata: public/private, name, CUDA version, supported GPUs. super_admin, gated\non image.create.", "operationId": "update_image_api_v1_images__image_id__patch", "parameters": [{"name": "image_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Image Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["images"], "summary": "Delete Image", "description": "Delete a catalogue image that no session has ever used. super_admin, gated on image.create.\n\nSessions keep a foreign key to their image for the audit trail, so an image with any session\nhistory cannot be deleted \u2014 retire it instead by setting ``public: false``.\n\nOwners may delete their OWN built (private) images; everything else stays admin-gated.", "operationId": "delete_image_api_v1_images__image_id__delete", "parameters": [{"name": "image_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Image Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/images/import": {"post": {"tags": ["images"], "summary": "Import Image", "description": "Register an image from an external registry reference. any authenticated.\n\nRegistration is synchronous catalog metadata: the actual pull happens on the GPU node's\ncontainer runtime when a session using the image first starts (there is no control-plane pull\nworker). The row is therefore created ``import_status=ready`` immediately. Private-registry\ncredentials are not supported yet \u2014 imagePullSecrets plumbing does not exist \u2014 so a request\ncarrying ``registry_auth`` is refused rather than silently losing the credential.\n\nWho owns the row:\n\n* ``image.create`` holders (super_admin) register SHARED catalog entries \u2014 ``owner_user_id``\n null, ``public`` as given. Re-registering a ref that already exists as a shared row is a 409.\n* everyone else registers a PRIVATE row they own (``public=false``, ``kind=container``), which\n only they and admins can see. The same public ref may therefore be imported by many members.\n\nAlways answers 202. Deduplication never fails the request: re-importing your own ref, or a ref\nthat is already in the shared catalogue, returns that row with ``existing: true`` instead of\ncreating a second one \u2014 the caller uses the returned ``id`` either way.", "operationId": "import_image_api_v1_images_import_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageImport"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/image-builds": {"post": {"tags": ["images"], "summary": "Create Build", "description": "Create a console image build: record desired state, then hand the GShareImageBuild CR to\nthe operator (which runs kaniko and reports back via /internal/image-builds/{id}/status).\n\nMembers build for themselves; the pushed image lands as a PRIVATE Image row\n(owner + admins only). One build in flight per user.", "operationId": "create_build_api_v1_image_builds_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BuildCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["images"], "summary": "List Builds", "description": "List builds. member sees own-project builds; restricted to membership projects.", "operationId": "list_builds_api_v1_image_builds_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "source", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Source"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageBuildList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/image-builds/{build_id}": {"get": {"tags": ["images"], "summary": "Get Build", "description": "Build detail incl. image_ref / scan summary.", "operationId": "get_build_api_v1_image_builds__build_id__get", "parameters": [{"name": "build_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Build Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/image-builds/{build_id}/logs": {"get": {"tags": ["images"], "summary": "Build Logs", "description": "Return the stored kaniko log tail (the operator reports the last ~16KB on each callback).", "operationId": "build_logs_api_v1_image_builds__build_id__logs_get", "parameters": [{"name": "build_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Build Id"}}, {"name": "tail", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 10000, "minimum": 1, "default": 500, "title": "Tail"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/events": {"get": {"tags": ["notifications"], "summary": "Notification Events", "description": "Live SSE stream of the caller's notifications: a ping event per new notification, which the\nconsole turns into a refetch of the list.\n\nEventSource cannot set headers, so authentication goes through ``?access_token=``, which\nget_current_principal accepts.", "operationId": "notification_events_api_v1_notifications_events_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications": {"get": {"tags": ["notifications"], "summary": "List Notifications", "description": "List the caller's own notifications, newest first. Self-scoped only.", "operationId": "list_notifications_api_v1_notifications_get", "parameters": [{"name": "unread", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Unread"}}, {"name": "include_deleted", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Include Deleted"}}, {"name": "type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "title": "Type"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["notifications"], "summary": "Delete All Notifications", "description": "Delete every notification of the caller. Self-scoped by construction.", "operationId": "delete_all_notifications_api_v1_notifications_delete", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/{notification_id}/read": {"post": {"tags": ["notifications"], "summary": "Mark Read", "description": "Mark one notification read; idempotent no-op if already read.", "operationId": "mark_read_api_v1_notifications__notification_id__read_post", "parameters": [{"name": "notification_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Notification Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/{notification_id}": {"delete": {"tags": ["notifications"], "summary": "Delete Notification", "description": "Delete one of the caller's notifications. 404 for other users' rows (no existence leak).", "operationId": "delete_notification_api_v1_notifications__notification_id__delete", "parameters": [{"name": "notification_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Notification Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/read-all": {"post": {"tags": ["notifications"], "summary": "Mark All Read", "description": "Bulk mark the caller's unread notifications read, optionally bounded.", "operationId": "mark_all_read_api_v1_notifications_read_all_post", "parameters": [{"name": "type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "title": "Type"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"type": "object", "additionalProperties": true}, {"type": "null"}], "title": "Body"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/audit-logs/export": {"get": {"tags": ["audit"], "summary": "Export Audit Logs", "description": "The current audit view as a CSV file, newest first, same scope and filters as the list.\n\nUTF-8 with a BOM so Excel opens Korean names correctly; ``detail`` is the JSON blob verbatim.\nTaking the export is itself audited (``audit.export``, with the filters and the row count):\na file leaving the system is exactly the kind of event the log exists for.", "operationId": "export_audit_logs_api_v1_audit_logs_export_get", "parameters": [{"name": "actor_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Id"}}, {"name": "actor_q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Q"}}, {"name": "action", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}}, {"name": "target", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target"}}, {"name": "at[gte]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Gte]"}}, {"name": "at[lt]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Lt]"}}, {"name": "result", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Result"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/audit-logs": {"get": {"tags": ["audit"], "summary": "List Audit Logs", "operationId": "list_audit_logs_api_v1_audit_logs_get", "parameters": [{"name": "actor_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Id"}}, {"name": "actor_q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Q"}}, {"name": "action", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}}, {"name": "target", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target"}}, {"name": "at[gte]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Gte]"}}, {"name": "at[lt]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Lt]"}}, {"name": "result", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Result"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "default": "-at", "title": "Sort"}}, {"name": "verify", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Verify"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AuditLogList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/webhooks": {"get": {"tags": ["webhooks"], "summary": "List Webhooks", "operationId": "list_webhooks_api_v1_webhooks_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["webhooks"], "summary": "Create Webhook", "operationId": "create_webhook_api_v1_webhooks_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebhookCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/webhooks/{webhook_id}": {"delete": {"tags": ["webhooks"], "summary": "Delete Webhook", "operationId": "delete_webhook_api_v1_webhooks__webhook_id__delete", "parameters": [{"name": "webhook_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Webhook Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/dashboard/summary": {"get": {"tags": ["dashboard"], "summary": "Dashboard Summary", "operationId": "dashboard_summary_api_v1_dashboard_summary_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"enum": ["mine", "managed"], "type": "string", "default": "mine", "title": "Scope"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DashboardSummary"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes": {"get": {"tags": ["infra"], "summary": "List Nodes", "description": "Nodes, optionally narrowed to one cluster.\n\nThe console filtered this list in the browser, which meant every screen fetched every\ncluster's nodes to show one cluster's. `GpuNode.cluster_id` is indexed; the filter belongs here.", "operationId": "list_nodes_api_v1_nodes_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "region", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Region"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NodeList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["infra"], "summary": "Register Node", "description": "Register a node, initially offline. super_admin only.\n\nWithout a cluster_id the node is attached to the only registered cluster, which covers test and\nsingle-cluster setups. With several clusters the field is required.", "operationId": "register_node_api_v1_nodes_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_NodeRegister"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}": {"get": {"tags": ["infra"], "summary": "Get Node", "description": "Fetch one node, for deep links from the drain and device pages.", "operationId": "get_node_api_v1_nodes__node_id__get", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["infra"], "summary": "Delete Node", "description": "Decommission a node: clear its inventory and have the operator remove it from Kubernetes.\n\nsuper_admin only. Two phases, because the control plane never calls the workload Kubernetes\nAPI itself. This request clears the cards and marks the node ``decommissioning``; the operator\ndeletes the Node object on its next pass and reports back, and only then does the row go. That\nis what stops a removed node from reappearing: while the Node object exists, every inventory\nreport recreates the row (upsert by cluster + hostname), which is exactly what a manual\n`kubectl delete node` used to be needed for.\n\nRefuses while the node still carries live work \u2014 a live allocation on one of its cards, or a\nnon-terminal session the operator placed there \u2014 so removal can never strand a running\nsession's ledger. Ended allocations keep their history: the row survives with device_id NULL\nand its gpu_uuid intact, since the card it names no longer exists.\n\nRefuses while the node is still up: deleting a live node's object only makes its kubelet\nregister again seconds later. Drain it and power it down first.", "operationId": "delete_node_api_v1_nodes__node_id__delete", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}/cordon": {"post": {"tags": ["infra"], "summary": "Cordon Node", "description": "Cordon or uncordon a node. super_admin only.\n\ncordon=true blocks new scheduling (status=cordoned); false restores it (status=ready). Sessions\nalready running are left alone.", "operationId": "cordon_node_api_v1_nodes__node_id__cordon_post", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_CordonBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}/drain": {"post": {"tags": ["infra"], "summary": "Drain Node", "description": "Drain a node. super_admin only.\n\nBoth modes cordon FIRST (no new placements can land back), then act on every session holding\na live allocation on the node's devices:\n - reschedule: pause \u2192 resume each running/preparing session. Resume re-runs placement,\n which excludes cordoned nodes \u2014 the session comes back on another eligible card (same\n GPU model, enough VRAM/cores, pool access). No capacity \u21d2 the session stays PAUSED\n (\"parked\"): work preserved, owner can resume later.\n - force_terminate: terminate each affected session (settled like an admin stop).", "operationId": "drain_node_api_v1_nodes__node_id__drain_post", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_DrainBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools": {"get": {"tags": ["infra"], "summary": "List Node Pools", "description": "List node pools. An org_admin sees only the pools carrying a grant for one of their\norganizations (or a group in them).", "operationId": "list_node_pools_api_v1_node_pools_get", "parameters": [{"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["infra"], "summary": "Create Node Pool", "operationId": "create_node_pool_api_v1_node_pools_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/app__api__schemas__node_pool__PoolCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools/{pool_id}": {"patch": {"tags": ["infra"], "summary": "Update Node Pool", "operationId": "update_node_pool_api_v1_node_pools__pool_id__patch", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["infra"], "summary": "Delete Node Pool", "description": "Delete a pool: its nodes become shared (pool_id NULL) and its grants go with it. Refused\nwhile any live session holds an allocation on one of its nodes \u2014 cordon and drain first.", "operationId": "delete_node_pool_api_v1_node_pools__pool_id__delete", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}/pool": {"put": {"tags": ["infra"], "summary": "Set Node Pool", "description": "Move a node into a pool (or back to shared with pool_id null). The pool must be in the\nnode's cluster. Sessions already on the node are left alone; only new placements change.", "operationId": "set_node_pool_api_v1_nodes__node_id__pool_put", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NodePoolSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools/{pool_id}/grants": {"post": {"tags": ["infra"], "summary": "Grant Node Pool", "description": "Grant a pool to an organization or group. super_admin: anything (the target must exist).\norg_admin: only sub-assignment of a pool already granted to their organization, to a group in\nthat organization (domain.node_pools.assert_may_grant).", "operationId": "grant_node_pool_api_v1_node_pools__pool_id__grants_post", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolGrantCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools/{pool_id}/grants/{grant_id}": {"delete": {"tags": ["infra"], "summary": "Revoke Node Pool Grant", "description": "Revoke a grant. Same rule as granting: an org_admin may only remove group grants inside an\norganization the pool is granted to.", "operationId": "revoke_node_pool_grant_api_v1_node_pools__pool_id__grants__grant_id__delete", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "grant_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Grant Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices": {"get": {"tags": ["infra"], "summary": "List Gpu Devices", "operationId": "list_gpu_devices_api_v1_gpu_devices_get", "parameters": [{"name": "node_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GpuDeviceList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices/{device_id}/alias": {"put": {"tags": ["infra"], "summary": "Set Device Alias", "description": "Name a physical card. super_admin only.\n\nThe console otherwise numbers cards by their position in the list, so \"card #2\" means a\ndifferent card the day a card is added or removed. An alias pins a name to the UUID. Unique\nwithin the cluster; the ledger owns it and inventory reports never overwrite it.", "operationId": "set_device_alias_api_v1_gpu_devices__device_id__alias_put", "parameters": [{"name": "device_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Device Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_DeviceAliasBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices/{device_id}/health": {"put": {"tags": ["infra"], "summary": "Set Device Health", "description": "Take one card out of service (or put it back). super_admin only.\n\n``unhealthy`` removes the card from placement and ends every session bound to it with\n``gpu_fault`` \u2014 a process whose CUDA context died cannot be resumed, so the honest outcome is\na settled session and a notified owner, not a running one that bills. ``ready`` puts the\ncard back after repair. The same routine serves operator health events that name a card.", "operationId": "set_device_health_api_v1_gpu_devices__device_id__health_put", "parameters": [{"name": "device_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Device Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_DeviceHealthBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices/{device_id}/mode": {"put": {"tags": ["infra"], "summary": "Set Gpu Device Mode", "description": "Set a card's target pool (per-CARD, not per-node). super_admin, same tier as cordon.\n\nfractional\u2194exclusive is a metadata change applied as soon as the card is empty; \u2194mig also\nneeds the node-side geometry change, executed by the drain state machine (the card stops\naccepting placements immediately and flips when its last allocation ends).", "operationId": "set_gpu_device_mode_api_v1_gpu_devices__device_id__mode_put", "parameters": [{"name": "device_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Device Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GpuDeviceModeSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-pools/{cluster_id}": {"put": {"tags": ["infra"], "summary": "Set Pool Targets", "description": "Set the cluster's MIG/hami-core pool split by TARGET COUNT \u2014 the console's coarse control\n(simpler and safer than dragging individual cards). The emptiest eligible cards are chosen;\neach transition drains first and runs through the GpuModeChange machinery.", "operationId": "set_pool_targets_api_v1_gpu_pools__cluster_id__put", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolTargetsBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/metrics/cluster": {"get": {"tags": ["infra"], "summary": "Metrics Cluster", "description": "Fleet figures, or one cluster's when `cluster_id` is given.\n\nWithout the filter the console showed a cluster's card grid beside fleet-wide totals \u2014 eight\nnodes and three cards while the panel below said one. Every aggregate here now narrows the\nsame way, so the numbers on one screen describe one thing.", "operationId": "metrics_cluster_api_v1_metrics_cluster_get", "parameters": [{"name": "region", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Region"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterMetrics"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/metrics/billing-report": {"get": {"tags": ["infra"], "summary": "Billing Report", "description": "Settlement and billing report: the credit ledger (consume, settle, topup) aggregated by a\ngroup_by key.\n\nConsumption and top-ups join CreditTransaction to CreditWallet and are attributed to the owner\n(organization, group, or user). gpu_hours is a best-effort sum of the occupancy hours of GPU\nsessions overlapping [from_, to].", "operationId": "billing_report_api_v1_metrics_billing_report_get", "parameters": [{"name": "scope", "in": "query", "required": true, "schema": {"type": "string", "pattern": "^(org|group|wallet)$", "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "from", "in": "query", "required": true, "schema": {"type": "string", "format": "date-time", "title": "From"}}, {"name": "to", "in": "query", "required": true, "schema": {"type": "string", "format": "date-time", "title": "To"}}, {"name": "group_by", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(group|offering|wallet)$", "default": "group", "title": "Group By"}}, {"name": "format", "in": "query", "required": false, "schema": {"type": "string", "default": "json", "title": "Format"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BillingReport"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/status": {"get": {"tags": ["monitoring"], "summary": "Monitoring Status", "description": "Whether the metrics backend answers, so the page can say \"not configured\" instead of\nrendering empty charts.", "operationId": "monitoring_status_api_v1_monitoring_status_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/sessions/{session_id}/usage": {"get": {"tags": ["monitoring"], "summary": "Session Usage", "description": "Measured live usage of ONE session's pod: cadvisor CPU/MEM + HAMi VRAM/GPU-core.\n\nInstant values for the monitor drawer, refreshed by the console. VRAM and core come from\nHAMi's in-container monitor, which only reports while a CUDA context exists \u2014 an idle\nnotebook legitimately reads 0 there while CPU/MEM still move.", "operationId": "session_usage_api_v1_monitoring_sessions__session_id__usage_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/sessions/{session_id}/usage/timeseries": {"get": {"tags": ["monitoring"], "summary": "Session Usage Timeseries", "description": "The four per-session usage metrics over a range, for the monitor detail sparklines. A\nfinished session gets its whole run instead of a trailing window.", "operationId": "session_usage_timeseries_api_v1_monitoring_sessions__session_id__usage_timeseries_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "default": "15m", "title": "Range"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/timeseries": {"get": {"tags": ["monitoring"], "summary": "Monitoring Timeseries", "description": "One panel over a time range. The panel id selects the query; the console never sends PromQL.", "operationId": "monitoring_timeseries_api_v1_monitoring_timeseries_get", "parameters": [{"name": "panel", "in": "query", "required": true, "schema": {"type": "string", "title": "Panel"}}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "default": "1h", "title": "Range"}}, {"name": "node", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node"}}, {"name": "gpu", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/instant": {"get": {"tags": ["monitoring"], "summary": "Monitoring Instant", "description": "Current value per series \u2014 the snapshot table and the tiles.", "operationId": "monitoring_instant_api_v1_monitoring_instant_get", "parameters": [{"name": "panel", "in": "query", "required": true, "schema": {"type": "string", "title": "Panel"}}, {"name": "node", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node"}}, {"name": "gpu", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/gpu-inventory": {"get": {"tags": ["monitoring"], "summary": "Monitoring Gpu Inventory", "description": "The ledger's view of each card: mode, allocated VRAM/cores, and the sessions holding it.\n\nDCGM cannot attribute a shared card's usage to a session (HAMi splits below its visibility), so\nsession attribution comes from the control plane instead of being guessed from metrics.", "operationId": "monitoring_gpu_inventory_api_v1_monitoring_gpu_inventory_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/system/branding": {"get": {"tags": ["system"], "summary": "Get Branding", "description": "Public: the sign-in screen renders this before anyone has a token.", "operationId": "get_branding_api_v1_system_branding_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BrandingOut"}}}}}}, "put": {"tags": ["system"], "summary": "Set Branding", "description": "Set the service name and logo; super_admin only.", "operationId": "set_branding_api_v1_system_branding_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BrandingUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BrandingOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/system/signup": {"get": {"tags": ["system"], "summary": "Get Signup Policy", "description": "Public: the sign-in screen shows its sign-up tab only when this is not `closed`.", "operationId": "get_signup_policy_api_v1_system_signup_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SignupPolicyOut"}}}}}}, "put": {"tags": ["system"], "summary": "Set Signup Policy", "description": "Set the sign-up policy; super_admin only.", "operationId": "set_signup_policy_api_v1_system_signup_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SignupPolicyUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SignupPolicyOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/system/placement": {"get": {"tags": ["system"], "summary": "Get Placement", "description": "The fractional-slice placement policy. Readable by anyone who may see the admin console.", "operationId": "get_placement_api_v1_system_placement_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlacementOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["system"], "summary": "Set Placement", "description": "Set the placement policy. Applies to the next reservation; running sessions do not move.", "operationId": "set_placement_api_v1_system_placement_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlacementUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlacementOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/sessions/{session_id}/status": {"post": {"tags": ["internal"], "summary": "Report Status", "operationId": "report_status_internal_sessions__session_id__status_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorStatusEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/image-builds/{build_id}/status": {"post": {"tags": ["internal"], "summary": "Report Build Status", "operationId": "report_build_status_internal_image_builds__build_id__status_post", "parameters": [{"name": "build_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Build Id"}}, {"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BuildStatusEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/connect/verify": {"get": {"tags": ["internal"], "summary": "Connect Verify", "operationId": "connect_verify_internal_connect_verify_get", "parameters": [{"name": "token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Token"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/audit/operator": {"post": {"tags": ["internal"], "summary": "Audit Operator", "operationId": "audit_operator_internal_audit_operator_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorAuditEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/inventory/gpu-devices": {"post": {"tags": ["internal"], "summary": "Upsert Gpu Device", "operationId": "upsert_gpu_device_internal_inventory_gpu_devices_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorGpuDeviceUpsert"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/inventory/nodes": {"post": {"tags": ["internal"], "summary": "Upsert Node", "operationId": "upsert_node_internal_inventory_nodes_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorNodeUpsert"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/cordoned": {"get": {"tags": ["internal"], "summary": "Cordoned Nodes", "description": "Hostnames the ledger holds as cordoned, for the operator to mirror onto the Kubernetes\nnodes (spec.unschedulable). The control plane never touches Kubernetes itself; without this\nmirror a gShare cordon only steered the ledger's card placement and kube-scheduler could still\nput a CPU session \u2014 or a resumed one \u2014 straight back on a node being drained.", "operationId": "cordoned_nodes_internal_nodes_cordoned_get", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/decommissioning": {"get": {"tags": ["internal"], "summary": "Decommissioning Nodes", "description": "Hostnames an administrator asked to remove from the cluster.\n\nThe console's delete button clears the ledger and parks the node here; the operator deletes\nthe matching Node object and calls back below. Without that second step the Node object\nsurvives, every inventory pass recreates the row, and the node reappears in the console \u2014\nwhich is why removing a node used to need a manual `kubectl delete node`.", "operationId": "decommissioning_nodes_internal_nodes_decommissioning_get", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/decommissioned": {"post": {"tags": ["internal"], "summary": "Node Decommissioned", "description": "The operator confirms the Node object is gone; the ledger row goes with it.", "operationId": "node_decommissioned_internal_nodes_decommissioned_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/inventory/drift": {"post": {"tags": ["internal"], "summary": "Report Drift", "operationId": "report_drift_internal_inventory_drift_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/health-events": {"post": {"tags": ["internal"], "summary": "Node Health Event", "description": "Record a NodeHealthEvent and, on a cordon action, mark GpuNode.status=cordoned.\n\nThe operator already cordoned the K8s node; the ledger reflects it so the console/scheduler\nstop placing new sessions there.\n\nThe operator's HealthReconciler addresses the node by its Kubernetes NAME (the hostname): it\nhas no ledger id. The row is therefore resolved by (token cluster, hostname) \u2014 with the ledger\nid still accepted for older callers \u2014 and the event carries the row's id, which the FK needs.\nLooking the hostname up as an id never matched: the cordon never reached the ledger and the\nevent insert violated the FK on Postgres.", "operationId": "node_health_event_internal_nodes_health_events_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorNodeHealthEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/.well-known/gshare-internal-jwks.json": {"get": {"tags": ["internal"], "summary": "Internal Jwks", "operationId": "internal_jwks__well_known_gshare_internal_jwks_json_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}}}, "/internal/volumes/sync": {"post": {"tags": ["internal"], "summary": "Sync Volumes", "operationId": "sync_volumes_internal_volumes_sync_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorVolumeSync"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeSyncResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/metrics/session-samples": {"post": {"tags": ["internal"], "summary": "Ingest Session Samples", "description": "Accept one node's batch of session samples.\n\nThe agent knows a session only by its CR name (the pod label), so the ids are resolved here \u2014\nthe same lower/underscore mapping the CR builder uses. An unknown name is dropped rather than\nstored under a key nothing will ever read.", "operationId": "ingest_session_samples_internal_metrics_session_samples_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentReport"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Response Ingest Session Samples Internal Metrics Session Samples Post"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/healthz": {"get": {"tags": ["health"], "summary": "Healthz", "operationId": "healthz_healthz_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}}}}, "components": {"schemas": {"AdjustBody": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "minimum": -1000000000000.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "reason": {"type": "string", "title": "Reason"}}, "type": "object", "required": ["amount", "reason"], "title": "AdjustBody"}, "AgentReport": {"properties": {"node": {"type": "string", "title": "Node"}, "samples": {"items": {"$ref": "#/components/schemas/AgentSample"}, "type": "array", "maxItems": 500, "title": "Samples"}}, "type": "object", "required": ["node"], "title": "AgentReport"}, "AgentSample": {"properties": {"session": {"type": "string", "title": "Session"}, "at": {"type": "number", "title": "At"}, "cpu_cores": {"type": "number", "minimum": 0.0, "title": "Cpu Cores"}, "mem_bytes": {"type": "integer", "minimum": 0.0, "title": "Mem Bytes"}}, "type": "object", "required": ["session", "at", "cpu_cores", "mem_bytes"], "title": "AgentSample"}, "AllocateBody": {"properties": {"from_wallet_id": {"type": "string", "title": "From Wallet Id"}, "to_wallet_id": {"type": "string", "title": "To Wallet Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["from_wallet_id", "to_wallet_id", "amount"], "title": "AllocateBody"}, "AllocationRejectBody": {"properties": {"reason": {"type": "string", "title": "Reason"}}, "type": "object", "required": ["reason"], "title": "AllocationRejectBody"}, "AllocationRequestCreate": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "level": {"type": "string", "pattern": "^(user|group|org)$", "title": "Level", "default": "user"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}, "note": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Note"}}, "type": "object", "required": ["amount"], "title": "AllocationRequestCreate"}, "AuditChainResult": {"properties": {"ok": {"type": "boolean", "title": "Ok"}, "checked": {"type": "integer", "title": "Checked"}, "broken_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Broken At"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["ok", "checked"], "title": "AuditChainResult", "description": "Optional integrity attestation appended when ``verify=true``."}, "AuditLogEntry": {"properties": {"id": {"type": "string", "title": "Id"}, "actor_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Id"}, "action": {"type": "string", "title": "Action"}, "target": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target"}, "result": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Result"}, "detail": {"additionalProperties": true, "type": "object", "title": "Detail"}, "trace_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Trace Id"}, "prev_hash": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Prev Hash"}, "entry_hash": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Entry Hash"}, "at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "At"}, "actor_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Name"}, "actor_email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Email"}, "target_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target Name"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, "type": "object", "required": ["id", "action", "detail"], "title": "AuditLogEntry", "description": "One audit-log row as projected by ``_audit_view`` (+ resolved actor_name)."}, "AuditLogList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/AuditLogEntry"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}, "names": {"additionalProperties": {"type": "string"}, "type": "object", "title": "Names", "default": {}}, "chain": {"anyOf": [{"$ref": "#/components/schemas/AuditChainResult"}, {"type": "null"}]}}, "type": "object", "required": ["data", "pagination"], "title": "AuditLogList", "description": "GET /audit-logs envelope (+ optional ``chain`` when verify=true)."}, "BillingReport": {"properties": {"rows": {"items": {"$ref": "#/components/schemas/BillingReportRow"}, "type": "array", "title": "Rows"}, "totals": {"additionalProperties": {"type": "string"}, "type": "object", "title": "Totals"}, "currency": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Currency"}}, "type": "object", "required": ["rows", "totals"], "title": "BillingReport"}, "BillingReportRow": {"properties": {"group": {"type": "string", "title": "Group"}, "group_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Name"}, "consumed": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Consumed"}, "topup": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Topup"}, "gpu_hours": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Hours"}}, "type": "object", "required": ["group"], "title": "BillingReportRow"}, "BoundSession": {"properties": {"session_id": {"type": "string", "title": "Session Id"}, "gpu_mem_mb": {"type": "integer", "title": "Gpu Mem Mb"}, "gpu_cores": {"type": "integer", "title": "Gpu Cores"}}, "type": "object", "required": ["session_id", "gpu_mem_mb", "gpu_cores"], "title": "BoundSession"}, "BrandingOut": {"properties": {"service_name": {"type": "string", "title": "Service Name"}, "logo": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Logo"}}, "type": "object", "required": ["service_name"], "title": "BrandingOut"}, "BrandingUpdate": {"properties": {"service_name": {"anyOf": [{"type": "string", "maxLength": 40, "minLength": 1}, {"type": "null"}], "title": "Service Name"}, "logo": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Logo"}, "clear_logo": {"type": "boolean", "title": "Clear Logo", "default": false}}, "type": "object", "title": "BrandingUpdate"}, "BudgetCreate": {"properties": {"scope": {"type": "string", "pattern": "^(org|group)$", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "period_start": {"type": "string", "format": "date-time", "title": "Period Start"}, "period": {"type": "string", "title": "Period", "default": "monthly"}, "limit_credit": {"anyOf": [{"type": "number", "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Limit Credit"}, "action": {"type": "string", "pattern": "^(alert|block)$", "title": "Action", "default": "alert"}}, "type": "object", "required": ["scope", "scope_id", "period_start", "limit_credit"], "title": "BudgetCreate"}, "BudgetForecast": {"properties": {"projected_exhaustion_date": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Projected Exhaustion Date"}, "burn_rate_per_day": {"type": "number", "title": "Burn Rate Per Day"}}, "type": "object", "required": ["burn_rate_per_day"], "title": "BudgetForecast"}, "BudgetRead": {"properties": {"id": {"type": "string", "title": "Id"}, "scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "limit_credit": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Limit Credit"}, "spent_credit": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Spent Credit"}, "action": {"type": "string", "title": "Action"}}, "type": "object", "required": ["id", "scope", "scope_id", "limit_credit", "spent_credit", "action"], "title": "BudgetRead"}, "BudgetUpdate": {"properties": {"limit_credit": {"anyOf": [{"type": "number", "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}, {"type": "null"}], "title": "Limit Credit"}, "action": {"anyOf": [{"type": "string", "pattern": "^(alert|block)$"}, {"type": "null"}], "title": "Action"}}, "type": "object", "title": "BudgetUpdate"}, "BuildCreate": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "source": {"type": "string", "title": "Source"}, "dockerfile": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Dockerfile"}, "git_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Git Url"}, "git_ref": {"type": "string", "title": "Git Ref", "default": "main"}, "context": {"type": "string", "title": "Context", "default": "."}, "build_args": {"additionalProperties": true, "type": "object", "title": "Build Args"}, "target_tag": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target Tag"}}, "type": "object", "required": ["group_id", "name", "source"], "title": "BuildCreate"}, "BuildStatusEvent": {"properties": {"phase": {"type": "string", "title": "Phase"}, "image_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Ref"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "log_tail": {"anyOf": [{"type": "string", "maxLength": 32768}, {"type": "null"}], "title": "Log Tail"}}, "type": "object", "required": ["phase"], "title": "BuildStatusEvent"}, "BulkAllocateBody": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["group_id", "amount"], "title": "BulkAllocateBody"}, "BulkMonthlyGrantBody": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "minimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}}, "type": "object", "required": ["group_id", "amount"], "title": "BulkMonthlyGrantBody"}, "BulkTerminateRequest": {"properties": {"session_ids": {"items": {"type": "string"}, "type": "array", "title": "Session Ids"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["session_ids"], "title": "BulkTerminateRequest"}, "BulkUserCreate": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "initial_role": {"type": "string", "title": "Initial Role", "default": "member"}, "rows": {"items": {"$ref": "#/components/schemas/BulkUserRow"}, "type": "array", "maxItems": 200, "minItems": 1, "title": "Rows"}}, "type": "object", "required": ["group_id", "rows"], "title": "BulkUserCreate"}, "BulkUserRow": {"properties": {"email": {"type": "string", "maxLength": 254, "minLength": 3, "title": "Email"}, "name": {"type": "string", "maxLength": 100, "minLength": 1, "title": "Name"}}, "type": "object", "required": ["email", "name"], "title": "BulkUserRow"}, "ChangePasswordRequest": {"properties": {"current_password": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Current Password"}, "new_password": {"type": "string", "maxLength": 128, "minLength": 8, "title": "New Password"}}, "type": "object", "required": ["new_password"], "title": "ChangePasswordRequest"}, "ClusterCompute": {"properties": {"cpu": {"$ref": "#/components/schemas/ClusterResource"}, "mem_gb": {"$ref": "#/components/schemas/ClusterResource"}, "disk_gb": {"$ref": "#/components/schemas/ClusterResource"}}, "type": "object", "required": ["cpu", "mem_gb", "disk_gb"], "title": "ClusterCompute"}, "ClusterCredit": {"properties": {"consumed_last_24h": {"type": "string", "title": "Consumed Last 24H"}, "active_holds": {"type": "string", "title": "Active Holds"}}, "type": "object", "required": ["consumed_last_24h", "active_holds"], "title": "ClusterCredit"}, "ClusterGpu": {"properties": {"device_total": {"type": "integer", "title": "Device Total"}, "vram_total_mb": {"type": "integer", "title": "Vram Total Mb"}, "vram_used_mb": {"type": "integer", "title": "Vram Used Mb"}, "vram_load_pct": {"type": "number", "title": "Vram Load Pct"}, "avg_utilization_pct": {"type": "number", "title": "Avg Utilization Pct"}, "empty_gpu_count": {"type": "integer", "title": "Empty Gpu Count"}}, "type": "object", "required": ["device_total", "vram_total_mb", "vram_used_mb", "vram_load_pct", "avg_utilization_pct", "empty_gpu_count"], "title": "ClusterGpu"}, "ClusterList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/ClusterRead"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}}, "type": "object", "required": ["data", "pagination"], "title": "ClusterList", "description": "GET /clusters envelope."}, "ClusterMetrics": {"properties": {"as_of": {"type": "string", "title": "As Of"}, "nodes": {"$ref": "#/components/schemas/ClusterNodes"}, "gpu": {"$ref": "#/components/schemas/ClusterGpu"}, "sessions": {"$ref": "#/components/schemas/ClusterSessions"}, "credit": {"$ref": "#/components/schemas/ClusterCredit"}, "compute": {"$ref": "#/components/schemas/ClusterCompute"}, "storage": {"anyOf": [{"$ref": "#/components/schemas/ClusterStorage"}, {"type": "null"}]}}, "type": "object", "required": ["as_of", "nodes", "gpu", "sessions", "credit", "compute"], "title": "ClusterMetrics"}, "ClusterNodes": {"properties": {"total": {"type": "integer", "title": "Total"}, "ready": {"type": "integer", "title": "Ready"}, "busy": {"type": "integer", "title": "Busy"}, "cordoned": {"type": "integer", "title": "Cordoned"}, "offline": {"type": "integer", "title": "Offline"}}, "type": "object", "required": ["total", "ready", "busy", "cordoned", "offline"], "title": "ClusterNodes"}, "ClusterPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80, "minLength": 1}, {"type": "null"}], "title": "Name"}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}, "session_domain": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Domain"}}, "type": "object", "title": "ClusterPatch"}, "ClusterRead": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "role": {"type": "string", "title": "Role"}, "api_server": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Api Server"}, "runtime": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Runtime"}, "session_domain": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Domain"}, "status": {"type": "string", "title": "Status"}, "node_count": {"type": "integer", "title": "Node Count"}, "gpu_count": {"type": "integer", "title": "Gpu Count"}, "registered_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Registered At"}}, "type": "object", "required": ["id", "name", "role", "status", "node_count", "gpu_count"], "title": "ClusterRead", "description": "One cluster as projected by ``_serialize_cluster`` (list rows)."}, "ClusterRegister": {"properties": {"name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "role": {"type": "string", "title": "Role"}, "kubeconfig_b64": {"type": "string", "title": "Kubeconfig B64"}, "session_domain": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Domain"}}, "type": "object", "required": ["name", "role", "kubeconfig_b64"], "title": "ClusterRegister"}, "ClusterResource": {"properties": {"used": {"type": "integer", "title": "Used"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["used", "total"], "title": "ClusterResource", "description": "One host-compute dimension fleet-wide: promised to active sessions vs node capacity."}, "ClusterSessions": {"properties": {"running": {"type": "integer", "title": "Running"}, "queued": {"type": "integer", "title": "Queued"}}, "type": "object", "required": ["running", "queued"], "title": "ClusterSessions"}, "ClusterStorage": {"properties": {"disk_gb": {"$ref": "#/components/schemas/ClusterStorageDisk"}, "node_count": {"type": "integer", "title": "Node Count", "default": 0}, "capacity_gb": {"type": "integer", "title": "Capacity Gb", "default": 0}, "unplaced_gb": {"type": "integer", "title": "Unplaced Gb", "default": 0}, "shared": {"type": "boolean", "title": "Shared", "default": false}, "pools": {"items": {"$ref": "#/components/schemas/ClusterStoragePool"}, "type": "array", "title": "Pools", "default": []}}, "type": "object", "required": ["disk_gb"], "title": "ClusterStorage"}, "ClusterStorageDisk": {"properties": {"used": {"type": "integer", "title": "Used"}, "total": {"type": "integer", "title": "Total"}, "source": {"type": "string", "title": "Source", "default": "node_disk"}}, "type": "object", "required": ["used", "total"], "title": "ClusterStorageDisk"}, "ClusterStoragePool": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "hostname": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Hostname"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "storage_class": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Storage Class"}, "share_scope": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Share Scope"}, "capacity_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Capacity Gb"}, "capacity_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Capacity Source"}, "capacity_reported_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Capacity Reported At"}, "used_gb": {"type": "integer", "title": "Used Gb", "default": 0}}, "type": "object", "required": ["id"], "title": "ClusterStoragePool", "description": "One registered volume-backing pool: what it is, where it sits, and who may use it."}, "ConnectionInfo": {"properties": {"kind": {"type": "string", "title": "Kind"}, "url": {"type": "string", "title": "Url"}, "connection_token": {"type": "string", "title": "Connection Token"}, "expires_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Expires At"}, "command": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Command"}}, "type": "object", "required": ["kind", "url", "connection_token"], "title": "ConnectionInfo"}, "DashboardAllocation": {"properties": {"instances": {"$ref": "#/components/schemas/DashboardInstances"}, "vram": {"$ref": "#/components/schemas/MyVram"}, "gpu_cores": {"anyOf": [{"$ref": "#/components/schemas/ResourceUsage"}, {"type": "null"}]}}, "type": "object", "required": ["instances", "vram"], "title": "DashboardAllocation"}, "DashboardCompute": {"properties": {"cpu": {"$ref": "#/components/schemas/ResourceUsage"}, "mem_gb": {"$ref": "#/components/schemas/ResourceUsage"}, "disk_gb": {"$ref": "#/components/schemas/ResourceUsage"}}, "type": "object", "required": ["cpu", "mem_gb", "disk_gb"], "title": "DashboardCompute", "description": "Host compute held by the caller's active sessions \u2014 separate from GPU/credits, since\ncpu/mem/disk are quota-governed, not billed."}, "DashboardCredit": {"properties": {"available": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Available"}, "balance": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Balance"}, "reserved": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Reserved"}}, "type": "object", "title": "DashboardCredit", "description": "Owner wallet snapshot; all None when the user has no wallet."}, "DashboardInstances": {"properties": {"used": {"type": "integer", "title": "Used"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["used", "total"], "title": "DashboardInstances"}, "DashboardPool": {"properties": {"id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "name": {"type": "string", "title": "Name"}, "kind": {"type": "string", "title": "Kind"}, "tier": {"type": "string", "title": "Tier"}}, "type": "object", "required": ["name", "kind", "tier"], "title": "DashboardPool", "description": "A node pool the caller may place on. `id` is None for the unassigned (\"shared\") bucket."}, "DashboardRegion": {"properties": {"model": {"type": "string", "title": "Model"}, "total": {"type": "integer", "title": "Total"}, "free": {"type": "integer", "title": "Free"}, "free_mb": {"type": "integer", "title": "Free Mb", "default": 0}, "total_mb": {"type": "integer", "title": "Total Mb", "default": 0}}, "type": "object", "required": ["model", "total", "free"], "title": "DashboardRegion", "description": "Per-GPU-model availability bucket.\n\n`free`/`total` count whole cards, which under fractional sharing understates what is usable: a\ncard holding one small slice is not \"free\" yet can still host several more sessions. The VRAM\nfigures are what actually decide whether a session starts, so both are reported."}, "DashboardSessions": {"properties": {"running": {"type": "integer", "title": "Running"}, "active": {"type": "integer", "title": "Active"}}, "type": "object", "required": ["running", "active"], "title": "DashboardSessions"}, "DashboardSummary": {"properties": {"credit": {"$ref": "#/components/schemas/DashboardCredit"}, "sessions": {"$ref": "#/components/schemas/DashboardSessions"}, "vram": {"$ref": "#/components/schemas/DashboardVram"}, "regions": {"items": {"$ref": "#/components/schemas/DashboardRegion"}, "type": "array", "title": "Regions"}, "pools": {"items": {"$ref": "#/components/schemas/DashboardPool"}, "type": "array", "title": "Pools", "default": []}, "allocation": {"$ref": "#/components/schemas/DashboardAllocation"}, "compute": {"$ref": "#/components/schemas/DashboardCompute"}, "storage": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Storage"}}, "type": "object", "required": ["credit", "sessions", "vram", "regions", "allocation", "compute"], "title": "DashboardSummary", "description": "GET /dashboard/summary aggregate."}, "DashboardVram": {"properties": {"used_mb": {"type": "integer", "title": "Used Mb"}, "total_mb": {"type": "integer", "title": "Total Mb"}}, "type": "object", "required": ["used_mb", "total_mb"], "title": "DashboardVram"}, "ForceTerminateBody": {"properties": {"reason": {"anyOf": [{"type": "string", "maxLength": 500}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "ForceTerminateBody", "description": "Admin's justification \u2014 recorded verbatim in the audit log (the console requires it)."}, "GlobalRoleSet": {"properties": {"global_roles": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Global Roles"}, "global_role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Global Role"}}, "type": "object", "title": "GlobalRoleSet"}, "GpuDeviceList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/GpuDeviceRow"}, "type": "array", "title": "Data"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["data", "total"], "title": "GpuDeviceList"}, "GpuDeviceModeSet": {"properties": {"desired_mode": {"anyOf": [{"type": "string", "pattern": "^(fractional|exclusive|mig)$"}, {"type": "null"}], "title": "Desired Mode"}}, "type": "object", "title": "GpuDeviceModeSet"}, "GpuDeviceRow": {"properties": {"id": {"type": "string", "title": "Id"}, "node_id": {"type": "string", "title": "Node Id"}, "model": {"type": "string", "title": "Model"}, "alias": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Alias"}, "mode": {"type": "string", "title": "Mode"}, "desired_mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Desired Mode"}, "mode_state": {"type": "string", "title": "Mode State", "default": "ready"}, "status": {"type": "string", "title": "Status"}, "node_status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Status"}, "gpu_uuid": {"type": "string", "title": "Gpu Uuid"}, "total_mem_mb": {"type": "integer", "title": "Total Mem Mb"}, "used_mem_mb": {"type": "integer", "title": "Used Mem Mb"}, "free_mem_mb": {"type": "integer", "title": "Free Mem Mb"}, "total_cores": {"type": "integer", "title": "Total Cores"}, "used_cores": {"type": "integer", "title": "Used Cores"}, "free_cores": {"type": "integer", "title": "Free Cores"}, "bound_sessions": {"items": {"$ref": "#/components/schemas/BoundSession"}, "type": "array", "title": "Bound Sessions"}}, "type": "object", "required": ["id", "node_id", "model", "mode", "status", "gpu_uuid", "total_mem_mb", "used_mem_mb", "free_mem_mb", "total_cores", "used_cores", "free_cores", "bound_sessions"], "title": "GpuDeviceRow"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "ImageBuildList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/ImageBuildRead"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}}, "type": "object", "required": ["data", "pagination"], "title": "ImageBuildList", "description": "GET /image-builds envelope."}, "ImageBuildRead": {"properties": {"id": {"type": "string", "title": "Id"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "owner_user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner User Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "source": {"type": "string", "title": "Source"}, "status": {"type": "string", "title": "Status"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "image_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Ref"}, "image_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Id"}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "started_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Started At"}, "finished_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Finished At"}}, "type": "object", "required": ["id", "source", "status"], "title": "ImageBuildRead", "description": "One build row as projected by ``_serialize_build``."}, "ImageCreate": {"properties": {"name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "registry": {"type": "string", "title": "Registry"}, "kind": {"type": "string", "title": "Kind"}, "tags": {"additionalProperties": true, "type": "object", "title": "Tags"}, "supported_gpus": {"items": {"type": "string"}, "type": "array", "title": "Supported Gpus"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "gpu_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Gpu Ready"}}, "type": "object", "required": ["name", "registry", "kind"], "title": "ImageCreate"}, "ImageImport": {"properties": {"source_type": {"type": "string", "title": "Source Type"}, "source": {"type": "string", "title": "Source"}, "name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "kind": {"type": "string", "title": "Kind"}, "registry_auth": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Registry Auth"}, "tags": {"additionalProperties": true, "type": "object", "title": "Tags"}, "supported_gpus": {"items": {"type": "string"}, "type": "array", "title": "Supported Gpus"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "gpu_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Gpu Ready"}}, "type": "object", "required": ["source_type", "source", "name", "kind"], "title": "ImageImport"}, "ImageList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/ImageRead"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}}, "type": "object", "required": ["data", "pagination"], "title": "ImageList", "description": "GET /images envelope."}, "ImageRead": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "registry": {"type": "string", "title": "Registry"}, "kind": {"type": "string", "title": "Kind"}, "tags": {"additionalProperties": true, "type": "object", "title": "Tags"}, "supported_gpus": {"items": {}, "type": "array", "title": "Supported Gpus"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "gpu_ready": {"type": "boolean", "title": "Gpu Ready", "default": false}, "public": {"type": "boolean", "title": "Public", "default": true}, "owner_user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner User Id"}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "import_status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Import Status"}}, "type": "object", "required": ["id", "name", "registry", "kind", "tags", "supported_gpus"], "title": "ImageRead", "description": "One catalog image as projected by ``_serialize_image``.\n\n``import_status`` is only present for imported/registered rows, so it is Optional."}, "ImageUpdate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "public": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Public"}, "registry": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Registry"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "supported_gpus": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Supported Gpus"}, "gpu_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Gpu Ready"}}, "type": "object", "title": "ImageUpdate"}, "MeMembership": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "project_name": {"type": "string", "title": "Project Name"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}, "org_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Name"}, "role": {"type": "string", "title": "Role"}, "has_group_admin": {"type": "boolean", "title": "Has Group Admin", "default": true}}, "type": "object", "required": ["group_id", "project_name", "role"], "title": "MeMembership", "description": "One membership row resolved for the context switcher / RBAC."}, "MeResponse": {"properties": {"user_id": {"type": "string", "title": "User Id"}, "global_role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Global Role"}, "global_roles": {"items": {"type": "string"}, "type": "array", "title": "Global Roles", "default": []}, "org_admin_orgs": {"items": {"type": "string"}, "type": "array", "title": "Org Admin Orgs", "default": []}, "memberships": {"items": {"$ref": "#/components/schemas/MeMembership"}, "type": "array", "title": "Memberships"}, "email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Email"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "must_change_password": {"type": "boolean", "title": "Must Change Password"}}, "type": "object", "required": ["user_id", "memberships", "must_change_password"], "title": "MeResponse", "description": "Identity/role/memberships of the current principal (GET /auth/me)."}, "MembershipCreate": {"properties": {"user_id": {"type": "string", "title": "User Id"}, "role": {"type": "string", "title": "Role"}, "expires_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Expires At"}, "grant_credit": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Grant Credit"}}, "type": "object", "required": ["user_id", "role"], "title": "MembershipCreate"}, "MembershipPatch": {"properties": {"role": {"type": "string", "title": "Role"}}, "type": "object", "required": ["role"], "title": "MembershipPatch"}, "MonthlyGrantBody": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "minimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}}, "type": "object", "required": ["amount"], "title": "MonthlyGrantBody"}, "MyVram": {"properties": {"used_mb": {"type": "integer", "title": "Used Mb"}, "limit_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Limit Mb"}}, "type": "object", "required": ["used_mb"], "title": "MyVram", "description": "The caller's own VRAM footprint vs their policy limit (None = unlimited)."}, "NodeList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/NodeRow"}, "type": "array", "title": "Data"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["data", "total"], "title": "NodeList"}, "NodePoolSet": {"properties": {"pool_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Id"}}, "type": "object", "title": "NodePoolSet"}, "NodeRow": {"properties": {"id": {"type": "string", "title": "Id"}, "hostname": {"type": "string", "title": "Hostname"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "status": {"type": "string", "title": "Status"}, "cpu": {"type": "integer", "title": "Cpu"}, "mem_gb": {"type": "integer", "title": "Mem Gb"}, "disk_gb": {"type": "integer", "title": "Disk Gb", "default": 0}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}, "region": {"type": "string", "title": "Region"}, "gpu_mode": {"type": "string", "title": "Gpu Mode"}, "mode_counts": {"additionalProperties": {"type": "integer"}, "type": "object", "title": "Mode Counts", "default": {}}, "device_count": {"type": "integer", "title": "Device Count"}, "alloc_cpu": {"type": "integer", "title": "Alloc Cpu", "default": 0}, "alloc_mem_gb": {"type": "integer", "title": "Alloc Mem Gb", "default": 0}, "alloc_disk_gb": {"type": "integer", "title": "Alloc Disk Gb", "default": 0}, "running_sessions": {"type": "integer", "title": "Running Sessions", "default": 0}, "heartbeat_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Heartbeat At"}, "pool_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Id"}, "pool_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Name"}}, "type": "object", "required": ["id", "hostname", "status", "cpu", "mem_gb", "region", "gpu_mode", "device_count"], "title": "NodeRow"}, "OfferingCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "resource_class": {"type": "string", "title": "Resource Class", "default": "gpu"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "credit_per_hour": {"type": "string", "title": "Credit Per Hour"}, "status": {"type": "string", "title": "Status", "default": "active"}, "min_cuda": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Min Cuda"}}, "type": "object", "required": ["name", "credit_per_hour"], "title": "OfferingCreate"}, "OfferingUpdate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "credit_per_hour": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Credit Per Hour"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "min_cuda": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Min Cuda"}}, "type": "object", "title": "OfferingUpdate"}, "OperatorAuditEvent": {"properties": {"actor": {"type": "string", "title": "Actor"}, "action": {"type": "string", "title": "Action"}, "target": {"type": "string", "title": "Target"}, "result": {"type": "string", "title": "Result"}, "detail": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Detail"}, "trace_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Trace Id"}, "ts": {"type": "string", "format": "date-time", "title": "Ts"}}, "type": "object", "required": ["actor", "action", "target", "result", "ts"], "title": "OperatorAuditEvent", "description": "Operator privileged-action audit callback."}, "OperatorGpuDeviceUpsert": {"properties": {"node_id": {"type": "string", "title": "Node Id"}, "uuid": {"type": "string", "title": "Uuid"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}, "total_mem_mb": {"type": "integer", "title": "Total Mem Mb", "default": 0}, "used_mem_mb": {"type": "integer", "title": "Used Mem Mb", "default": 0}, "total_cores": {"type": "integer", "title": "Total Cores", "default": 0}, "used_cores": {"type": "integer", "title": "Used Cores", "default": 0}, "status": {"type": "string", "title": "Status", "default": "ready"}, "model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Model"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "node_cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Cpu"}, "node_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Node Ready"}, "node_mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Mem Gb"}, "node_disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Disk Gb"}}, "type": "object", "required": ["node_id", "uuid"], "title": "OperatorGpuDeviceUpsert", "description": "GPU device inventory upsert (operator InventoryReconciler -> ledger).\n\nPure reflection of measured device-plugin/DCGM capacity. The control plane preserves\nledger-owned occupancy (used_mem_mb/used_cores) \u2014 those are NOT overwritten from here."}, "OperatorNodeHealthEvent": {"properties": {"node_id": {"type": "string", "title": "Node Id"}, "kind": {"type": "string", "title": "Kind"}, "severity": {"type": "string", "title": "Severity", "default": "critical"}, "action": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}, "gpu_uuid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Uuid"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}}, "type": "object", "required": ["node_id", "kind"], "title": "OperatorNodeHealthEvent", "description": "Node health transition (operator HealthReconciler -> ledger).\n\nOn a critical breach (e.g. fatal Xid) the operator cordons the node and reports this; the\ncontrol plane records a NodeHealthEvent and marks GpuNode.status=cordoned."}, "OperatorNodeUpsert": {"properties": {"node_id": {"type": "string", "title": "Node Id"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "node_cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Cpu"}, "node_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Node Ready"}, "node_mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Mem Gb"}, "node_disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Disk Gb"}, "lossless_capable": {"type": "boolean", "title": "Lossless Capable", "default": false}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}}, "type": "object", "required": ["node_id"], "title": "OperatorNodeUpsert", "description": "Upsert node inventory, reporting capacity for every node whether or not it has a GPU.\n\nGPU-less nodes \u2014 CPU workers and the control plane \u2014 still contribute their cpu, mem, and disk\nto the displayed inventory and the capacity calculation. "}, "OperatorPoolCapacity": {"properties": {"storage_class": {"type": "string", "title": "Storage Class"}, "capacity_bytes": {"type": "integer", "minimum": 0.0, "title": "Capacity Bytes"}}, "type": "object", "required": ["storage_class", "capacity_bytes"], "title": "OperatorPoolCapacity", "description": "What the CSI driver says a StorageClass's backing pool holds.\n\nRead from the CSIStorageCapacity objects the external-provisioner publishes. The control plane\ncannot ask a CSI driver anything \u2014 it never touches the workload API \u2014 and the only figure it\ncould see on its own is the storage node's root disk, which is not the pool."}, "OperatorSessionDisk": {"properties": {"name": {"type": "string", "title": "Name"}, "ephemeral_used_bytes": {"type": "integer", "title": "Ephemeral Used Bytes"}, "ephemeral_limit_bytes": {"type": "integer", "title": "Ephemeral Limit Bytes"}}, "type": "object", "required": ["name", "ephemeral_used_bytes", "ephemeral_limit_bytes"], "title": "OperatorSessionDisk", "description": "Ephemeral (scratch) disk usage of one session pod, read from kubelet /stats/summary.\n\n``name`` is the GShareSession CR name \u2014 the sanitized session id (``ses-01abc...``)."}, "OperatorStatusEvent": {"properties": {"phase": {"type": "string", "title": "Phase"}, "bound_gpu_uuid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Bound Gpu Uuid"}, "node_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Name"}, "yield_state": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Yield State"}, "pod_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pod Ref"}, "used_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Used Mem Mb"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "trace_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Trace Id"}, "restart_count": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Restart Count"}, "generation": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Generation"}, "container_state": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Container State"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "ts": {"type": "string", "format": "date-time", "title": "Ts"}}, "type": "object", "required": ["phase", "ts"], "title": "OperatorStatusEvent", "description": "Status callback payload. Drives consume/settle triggers."}, "OperatorVolumeObserved": {"properties": {"name": {"type": "string", "title": "Name"}, "volume_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Volume Id"}, "capacity_gb": {"type": "integer", "title": "Capacity Gb", "default": 0}, "used_bytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Used Bytes"}, "mounted": {"type": "boolean", "title": "Mounted", "default": false}, "storage_class": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Storage Class"}}, "type": "object", "required": ["name"], "title": "OperatorVolumeObserved", "description": "One PVC the operator sees in the session namespace (label gshare.io/volume)."}, "OperatorVolumeSync": {"properties": {"volumes": {"items": {"$ref": "#/components/schemas/OperatorVolumeObserved"}, "type": "array", "title": "Volumes"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "sessions": {"items": {"$ref": "#/components/schemas/OperatorSessionDisk"}, "type": "array", "title": "Sessions", "default": []}, "pools": {"items": {"$ref": "#/components/schemas/OperatorPoolCapacity"}, "type": "array", "title": "Pools", "default": []}}, "type": "object", "required": ["volumes"], "title": "OperatorVolumeSync", "description": "POST /internal/volumes/sync \u2014 the operator's periodic view of every session-volume PVC."}, "OrgAdminCreate": {"properties": {"user_id": {"type": "string", "title": "User Id"}}, "type": "object", "required": ["user_id"], "title": "OrgAdminCreate"}, "OrgCreate": {"properties": {"name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "create_node_pool": {"type": "boolean", "title": "Create Node Pool", "default": false}}, "type": "object", "required": ["name"], "title": "OrgCreate"}, "OrgUpdate": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80}, {"type": "null"}], "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, "type": "object", "title": "OrgUpdate"}, "PageMeta": {"properties": {"page": {"type": "integer", "title": "Page"}, "size": {"type": "integer", "title": "Size"}, "total": {"type": "integer", "title": "Total"}, "total_pages": {"type": "integer", "title": "Total Pages"}}, "type": "object", "required": ["page", "size", "total", "total_pages"], "title": "PageMeta", "description": "Standard pagination envelope (page/size/total/total_pages)."}, "PageMetaNoPages": {"properties": {"page": {"type": "integer", "title": "Page"}, "size": {"type": "integer", "title": "Size"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["page", "size", "total"], "title": "PageMetaNoPages", "description": "Pagination envelope without ``total_pages`` (queue list)."}, "PermissionBody": {"properties": {"user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User Id"}, "email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Email"}, "role": {"type": "string", "pattern": "^(owner|rw|ro)$", "title": "Role"}}, "type": "object", "required": ["role"], "title": "PermissionBody"}, "PlacementOut": {"properties": {"gpu_packing": {"type": "string", "title": "Gpu Packing"}}, "type": "object", "required": ["gpu_packing"], "title": "PlacementOut"}, "PlacementUpdate": {"properties": {"gpu_packing": {"type": "string", "pattern": "^(binpack|spread)$", "title": "Gpu Packing"}}, "type": "object", "required": ["gpu_packing"], "title": "PlacementUpdate"}, "PolicyCreate": {"properties": {"scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "max_concurrent": {"type": "integer", "title": "Max Concurrent"}, "max_queued": {"type": "integer", "title": "Max Queued"}, "max_runtime_min": {"type": "integer", "title": "Max Runtime Min"}, "idle_timeout_sec": {"type": "integer", "title": "Idle Timeout Sec"}, "cpu_session_max_concurrent": {"type": "integer", "title": "Cpu Session Max Concurrent", "default": 1}, "cpu_session_max_runtime_min": {"type": "integer", "title": "Cpu Session Max Runtime Min", "default": 240}, "cpu_session_idle_timeout_sec": {"type": "integer", "title": "Cpu Session Idle Timeout Sec", "default": 1800}, "limits": {"additionalProperties": true, "type": "object", "title": "Limits", "default": {}}}, "type": "object", "required": ["scope", "scope_id", "max_concurrent", "max_queued", "max_runtime_min", "idle_timeout_sec"], "title": "PolicyCreate"}, "PolicyUpdate": {"properties": {"max_concurrent": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Max Concurrent"}, "max_queued": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Max Queued"}, "max_runtime_min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Max Runtime Min"}, "idle_timeout_sec": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Idle Timeout Sec"}, "cpu_session_max_concurrent": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu Session Max Concurrent"}, "cpu_session_max_runtime_min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu Session Max Runtime Min"}, "cpu_session_idle_timeout_sec": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu Session Idle Timeout Sec"}, "limits": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Limits"}}, "type": "object", "title": "PolicyUpdate"}, "PoolGrantCreate": {"properties": {"scope": {"type": "string", "pattern": "^(org|group)$", "title": "Scope"}, "scope_id": {"type": "string", "minLength": 1, "title": "Scope Id"}}, "type": "object", "required": ["scope", "scope_id"], "title": "PoolGrantCreate"}, "PoolGrantRead": {"properties": {"id": {"type": "string", "title": "Id"}, "scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "created_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Created At"}}, "type": "object", "required": ["id", "scope", "scope_id"], "title": "PoolGrantRead"}, "PoolList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/PoolRead"}, "type": "array", "title": "Data"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["data", "total"], "title": "PoolList"}, "PoolNodeRow": {"properties": {"id": {"type": "string", "title": "Id"}, "hostname": {"type": "string", "title": "Hostname"}, "status": {"type": "string", "title": "Status"}, "device_count": {"type": "integer", "title": "Device Count"}}, "type": "object", "required": ["id", "hostname", "status", "device_count"], "title": "PoolNodeRow"}, "PoolPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80, "minLength": 1}, {"type": "null"}], "title": "Name"}, "storage_class": {"anyOf": [{"type": "string", "maxLength": 200, "minLength": 1}, {"type": "null"}], "title": "Storage Class"}, "node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}, "share_scope": {"anyOf": [{"type": "string", "pattern": "^(all|selected)$"}, {"type": "null"}], "title": "Share Scope"}, "shared_with": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Shared With"}, "manual_capacity_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Manual Capacity Gb"}}, "type": "object", "title": "PoolPatch"}, "PoolRead": {"properties": {"id": {"type": "string", "title": "Id"}, "cluster_id": {"type": "string", "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "name": {"type": "string", "title": "Name"}, "description": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Description"}, "kind": {"type": "string", "title": "Kind"}, "node_count": {"type": "integer", "title": "Node Count"}, "nodes": {"items": {"$ref": "#/components/schemas/PoolNodeRow"}, "type": "array", "title": "Nodes"}, "grants": {"items": {"$ref": "#/components/schemas/PoolGrantRead"}, "type": "array", "title": "Grants"}}, "type": "object", "required": ["id", "cluster_id", "name", "kind", "node_count", "nodes", "grants"], "title": "PoolRead"}, "PoolTargetsBody": {"properties": {"mig_cards": {"type": "integer", "minimum": 0.0, "title": "Mig Cards"}}, "type": "object", "required": ["mig_cards"], "title": "PoolTargetsBody"}, "PoolUpdate": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 120, "minLength": 1}, {"type": "null"}], "title": "Name"}, "description": {"anyOf": [{"type": "string", "maxLength": 1000}, {"type": "null"}], "title": "Description"}, "kind": {"anyOf": [{"type": "string", "pattern": "^(shared|dedicated)$"}, {"type": "null"}], "title": "Kind"}}, "type": "object", "title": "PoolUpdate"}, "PresetCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "kind": {"type": "string", "title": "Kind", "default": "gpu"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "gpu_frac": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Gpu Frac"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}}, "type": "object", "required": ["name"], "title": "PresetCreate"}, "PresetUpdate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "gpu_frac": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Gpu Frac"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}}, "type": "object", "title": "PresetUpdate"}, "PreviewCostRequest": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "offering_id": {"type": "string", "title": "Offering Id"}, "image_id": {"type": "string", "title": "Image Id"}, "resource_class": {"type": "string", "pattern": "^(gpu|cpu)$", "title": "Resource Class"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_mode": {"type": "string", "pattern": "^(single|multi)$", "title": "Cluster Mode", "default": "single"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "gpu_mem_mb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer", "maximum": 100.0, "minimum": 0.0}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Disk Gb"}, "mode": {"anyOf": [{"type": "string", "pattern": "^(fractional|exclusive)$"}, {"type": "null"}], "title": "Mode"}, "billing_wallet_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Billing Wallet Id"}, "preemptible": {"type": "boolean", "title": "Preemptible", "default": false}, "privileged": {"type": "boolean", "title": "Privileged", "default": false}, "priority": {"type": "integer", "minimum": 0.0, "title": "Priority", "default": 0}, "volume_mounts": {"items": {"$ref": "#/components/schemas/VolumeMountSpec"}, "type": "array", "title": "Volume Mounts", "default": []}}, "additionalProperties": false, "type": "object", "required": ["offering_id", "image_id", "resource_class"], "title": "PreviewCostRequest"}, "PreviewCostResponse": {"properties": {"estimated_credit_per_hour": {"type": "number", "title": "Estimated Credit Per Hour"}, "occupancy": {"type": "number", "title": "Occupancy"}, "hold_amount": {"type": "number", "title": "Hold Amount"}}, "type": "object", "required": ["estimated_credit_per_hour", "occupancy", "hold_amount"], "title": "PreviewCostResponse"}, "ProjectCreate": {"properties": {"org_id": {"type": "string", "title": "Org Id"}, "name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "create_project_wallet": {"type": "boolean", "title": "Create Project Wallet", "default": true}, "default_member_credit": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Default Member Credit"}, "create_node_pool": {"type": "boolean", "title": "Create Node Pool", "default": false}}, "type": "object", "required": ["org_id", "name"], "title": "ProjectCreate"}, "ProjectPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80}, {"type": "null"}], "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "default_member_credit": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Default Member Credit"}}, "type": "object", "title": "ProjectPatch"}, "QueueEntryView": {"properties": {"id": {"type": "string", "title": "Id"}, "session_id": {"type": "string", "title": "Session Id"}, "priority": {"type": "integer", "title": "Priority"}, "status": {"type": "string", "title": "Status"}, "position": {"type": "integer", "title": "Position"}, "score": {"type": "number", "title": "Score"}, "session_req": {"additionalProperties": true, "type": "object", "title": "Session Req"}, "enqueued_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Enqueued At"}, "eta_minutes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Eta Minutes"}, "session_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Name"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["id", "session_id", "priority", "status", "position", "score", "session_req"], "title": "QueueEntryView", "description": "One queue entry as projected by ``_entry_view`` (status is always ``queued``)."}, "QueueList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/QueueEntryView"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMetaNoPages"}}, "type": "object", "required": ["data", "pagination"], "title": "QueueList", "description": "GET /queue envelope (pagination without total_pages)."}, "QueueMineList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/QueueEntryView"}, "type": "array", "title": "Data"}}, "type": "object", "required": ["data"], "title": "QueueMineList", "description": "GET /queue/mine envelope (data only, no pagination)."}, "QueuePriorityPatch": {"properties": {"priority": {"type": "integer", "minimum": 0.0, "title": "Priority"}}, "type": "object", "required": ["priority"], "title": "QueuePriorityPatch"}, "RefillScheduleBody": {"properties": {"day": {"type": "integer", "maximum": 28.0, "minimum": 1.0, "title": "Day"}, "hour": {"type": "integer", "maximum": 23.0, "minimum": 0.0, "title": "Hour"}}, "type": "object", "required": ["day", "hour"], "title": "RefillScheduleBody"}, "ResourceRequestCreate": {"properties": {"group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "storage_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Storage Gb"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "note": {"type": "string", "title": "Note"}}, "type": "object", "required": ["note"], "title": "ResourceRequestCreate"}, "ResourceUsage": {"properties": {"used": {"type": "integer", "title": "Used"}, "limit": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Limit"}}, "type": "object", "required": ["used"], "title": "ResourceUsage", "description": "One compute dimension: what the caller's active sessions hold vs the policy limit\n(None = no limit configured)."}, "SessionCreate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "offering_id": {"type": "string", "title": "Offering Id"}, "image_id": {"type": "string", "title": "Image Id"}, "resource_class": {"type": "string", "pattern": "^(gpu|cpu)$", "title": "Resource Class"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_mode": {"type": "string", "pattern": "^(single|multi)$", "title": "Cluster Mode", "default": "single"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "gpu_mem_mb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer", "maximum": 100.0, "minimum": 0.0}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Disk Gb"}, "mode": {"anyOf": [{"type": "string", "pattern": "^(fractional|exclusive)$"}, {"type": "null"}], "title": "Mode"}, "billing_wallet_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Billing Wallet Id"}, "preemptible": {"type": "boolean", "title": "Preemptible", "default": false}, "privileged": {"type": "boolean", "title": "Privileged", "default": false}, "priority": {"type": "integer", "minimum": 0.0, "title": "Priority", "default": 0}, "volume_mounts": {"items": {"$ref": "#/components/schemas/VolumeMountSpec"}, "type": "array", "title": "Volume Mounts", "default": []}}, "additionalProperties": false, "type": "object", "required": ["offering_id", "image_id", "resource_class"], "title": "SessionCreate"}, "SessionMountRead": {"properties": {"volume_id": {"type": "string", "title": "Volume Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "quota_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Quota Gb"}, "mount_path": {"type": "string", "title": "Mount Path"}, "mode": {"type": "string", "title": "Mode"}}, "type": "object", "required": ["volume_id", "mount_path", "mode"], "title": "SessionMountRead", "description": "One mounted volume, joined with its display facts for the detail screens."}, "SessionRead": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "status": {"type": "string", "title": "Status"}, "status_reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status Reason"}, "occupancy": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Occupancy"}, "bound_gpu_uuid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Bound Gpu Uuid"}, "node_hostname": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Hostname"}, "node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}, "cluster_id": {"type": "string", "title": "Cluster Id"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "group_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Name"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}, "org_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Name"}, "resource_class": {"type": "string", "title": "Resource Class"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "gpu_alias": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Alias"}, "image_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Name"}, "image_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Ref"}, "disk_used_bytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Used Bytes"}, "disk_limit_bytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Limit Bytes"}, "mounts": {"items": {"$ref": "#/components/schemas/SessionMountRead"}, "type": "array", "title": "Mounts", "default": []}, "owner_user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner User Id"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "credit_per_hour_snapshot": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Credit Per Hour Snapshot"}, "started_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Started At"}, "terminated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Terminated At"}, "usage_summary": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Usage Summary"}, "credit_consumed": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Credit Consumed"}, "queued_reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Queued Reason"}, "privileged": {"type": "boolean", "title": "Privileged", "default": false}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "status_changed_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Status Changed At"}}, "type": "object", "required": ["id", "status", "cluster_id", "resource_class"], "title": "SessionRead"}, "SignupPolicyOut": {"properties": {"mode": {"type": "string", "title": "Mode"}, "allowed_domains": {"items": {"type": "string"}, "type": "array", "title": "Allowed Domains", "default": []}}, "type": "object", "required": ["mode"], "title": "SignupPolicyOut"}, "SignupPolicyUpdate": {"properties": {"mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}, "allowed_domains": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Allowed Domains"}}, "type": "object", "title": "SignupPolicyUpdate"}, "SpendDayRead": {"properties": {"date": {"type": "string", "title": "Date"}, "amount": {"type": "number", "title": "Amount"}}, "type": "object", "required": ["date", "amount"], "title": "SpendDayRead", "description": "One day of spend (consume + storage), for the wallet's usage chart."}, "TopupRejectBody": {"properties": {"reason": {"type": "string", "minLength": 1, "title": "Reason"}}, "type": "object", "required": ["reason"], "title": "TopupRejectBody"}, "TopupRequestBody": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "note": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Note"}, "wallet_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Id"}}, "type": "object", "required": ["amount"], "title": "TopupRequestBody"}, "TopupRequestListResponse": {"properties": {"data": {"items": {"$ref": "#/components/schemas/TopupRequestRead"}, "type": "array", "title": "Data"}}, "type": "object", "required": ["data"], "title": "TopupRequestListResponse"}, "TopupRequestRead": {"properties": {"id": {"type": "string", "title": "Id"}, "wallet_id": {"type": "string", "title": "Wallet Id"}, "amount": {"type": "string", "title": "Amount"}, "status": {"type": "string", "title": "Status"}, "requester_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Requester Id"}, "requester_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Requester Name"}, "note": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Note"}, "wallet_owner_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Owner Type"}, "wallet_owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Owner Name"}, "decided_reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Decided Reason"}, "decided_by": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Decided By"}, "created_at": {"type": "string", "title": "Created At"}}, "type": "object", "required": ["id", "wallet_id", "amount", "status", "created_at"], "title": "TopupRequestRead"}, "TransactionRead": {"properties": {"id": {"type": "string", "title": "Id"}, "type": {"type": "string", "title": "Type"}, "amount": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Amount"}, "balance_after": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Balance After"}, "ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Ref"}, "ref_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Ref Name"}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "entry_count": {"type": "integer", "title": "Entry Count", "default": 1}, "period_start": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Period Start"}, "period_end": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Period End"}, "settled": {"type": "boolean", "title": "Settled", "default": false}, "live": {"type": "boolean", "title": "Live", "default": false}}, "type": "object", "required": ["id", "type", "amount", "balance_after"], "title": "TransactionRead"}, "TransferBody": {"properties": {"to_wallet_id": {"type": "string", "title": "To Wallet Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}}, "type": "object", "required": ["to_wallet_id", "amount"], "title": "TransferBody"}, "UserApproveBody": {"properties": {"group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "initial_role": {"type": "string", "title": "Initial Role", "default": "member"}}, "type": "object", "title": "UserApproveBody", "description": "Department is optional: an administrator may let someone in and sort out the department\nlater, but doing both at once is the normal path."}, "UserCreate": {"properties": {"email": {"type": "string", "maxLength": 254, "minLength": 3, "title": "Email"}, "name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "group_id": {"type": "string", "title": "Group Id"}, "status": {"type": "string", "title": "Status", "default": "active"}, "initial_role": {"type": "string", "title": "Initial Role", "default": "member"}, "password": {"type": "string", "maxLength": 128, "minLength": 8, "title": "Password"}}, "type": "object", "required": ["email", "name", "group_id", "password"], "title": "UserCreate"}, "UserDepartmentSet": {"properties": {"group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, "type": "object", "title": "UserDepartmentSet"}, "UserPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80}, {"type": "null"}], "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "email": {"anyOf": [{"type": "string", "maxLength": 254, "minLength": 3}, {"type": "null"}], "title": "Email"}, "password": {"anyOf": [{"type": "string", "maxLength": 128, "minLength": 8}, {"type": "null"}], "title": "Password"}, "force_password_reset": {"type": "boolean", "title": "Force Password Reset", "default": false}}, "additionalProperties": false, "type": "object", "title": "UserPatch"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}, "input": {"title": "Input"}, "ctx": {"type": "object", "title": "Context"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}, "VolumeCreate": {"properties": {"scope": {"type": "string", "pattern": "^(user|group|global)$", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "type": {"type": "string", "pattern": "^(home|group|dataset|scratch)$", "title": "Type"}, "name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "access_mode": {"type": "string", "pattern": "^(RWO|RWX|ROX)$", "title": "Access Mode"}, "quota_gb": {"type": "integer", "minimum": 0.0, "title": "Quota Gb"}}, "type": "object", "required": ["scope", "scope_id", "type", "name", "access_mode", "quota_gb"], "title": "VolumeCreate"}, "VolumeMountSpec": {"properties": {"volume_id": {"type": "string", "title": "Volume Id"}, "mount_path": {"type": "string", "title": "Mount Path"}, "mode": {"type": "string", "pattern": "^(ro|rw)$", "title": "Mode", "default": "rw"}}, "additionalProperties": false, "type": "object", "required": ["volume_id", "mount_path"], "title": "VolumeMountSpec"}, "VolumePatch": {"properties": {"quota_gb": {"anyOf": [{"type": "integer", "minimum": 1.0}, {"type": "null"}], "title": "Quota Gb"}, "access_mode": {"anyOf": [{"type": "string", "pattern": "^(RWO|RWX|ROX)$"}, {"type": "null"}], "title": "Access Mode"}, "mount_locked": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Mount Locked"}}, "additionalProperties": false, "type": "object", "title": "VolumePatch", "description": "Owner-side edits. The quota only grows (bounded above by the scope's storage policy on the\nserver); `mount_locked` blocks new mounts so the volume can be drained for deletion."}, "VolumeRead": {"properties": {"id": {"type": "string", "title": "Id"}, "scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "type": {"type": "string", "title": "Type"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "access_mode": {"type": "string", "title": "Access Mode"}, "quota_gb": {"type": "integer", "title": "Quota Gb"}, "used_gb": {"type": "integer", "title": "Used Gb"}, "mount_locked": {"type": "boolean", "title": "Mount Locked", "default": false}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}, "owner_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Id"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "shared_count": {"type": "integer", "title": "Shared Count", "default": 0}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "storage_class": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Storage Class"}, "pool_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Id"}, "pool_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Name"}, "active_mounts": {"anyOf": [{"items": {"additionalProperties": true, "type": "object"}, "type": "array"}, {"type": "null"}], "title": "Active Mounts"}}, "type": "object", "required": ["id", "scope", "scope_id", "type", "access_mode", "quota_gb", "used_gb"], "title": "VolumeRead"}, "VolumeSyncDirective": {"properties": {"name": {"type": "string", "title": "Name"}, "volume_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Volume Id"}, "quota_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Quota Gb"}, "reclaim": {"type": "boolean", "title": "Reclaim", "default": false}}, "type": "object", "required": ["name"], "title": "VolumeSyncDirective", "description": "What the control plane wants for one observed PVC."}, "VolumeSyncResponse": {"properties": {"volumes": {"items": {"$ref": "#/components/schemas/VolumeSyncDirective"}, "type": "array", "title": "Volumes"}, "orphans": {"type": "integer", "title": "Orphans", "default": 0}}, "type": "object", "required": ["volumes"], "title": "VolumeSyncResponse"}, "WalletRead": {"properties": {"id": {"type": "string", "title": "Id"}, "owner_type": {"type": "string", "title": "Owner Type"}, "owner_id": {"type": "string", "title": "Owner Id"}, "balance": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Balance"}, "reserved": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Reserved"}, "monthly_grant": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Monthly Grant", "default": "0"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "available": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Available", "readOnly": true}}, "type": "object", "required": ["id", "owner_type", "owner_id", "balance", "reserved", "available"], "title": "WalletRead"}, "WebhookCreate": {"properties": {"url": {"type": "string", "title": "Url"}, "events": {"items": {"type": "string"}, "type": "array", "title": "Events"}, "secret": {"type": "string", "title": "Secret"}, "scope": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Scope"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}}, "type": "object", "required": ["url", "events", "secret"], "title": "WebhookCreate"}, "_CordonBody": {"properties": {"cordon": {"type": "boolean", "title": "Cordon", "default": true}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "_CordonBody"}, "_DeviceAliasBody": {"properties": {"alias": {"anyOf": [{"type": "string", "maxLength": 32}, {"type": "null"}], "title": "Alias"}}, "type": "object", "title": "_DeviceAliasBody"}, "_DeviceHealthBody": {"properties": {"status": {"type": "string", "enum": ["ready", "unhealthy"], "title": "Status"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["status"], "title": "_DeviceHealthBody"}, "_DrainBody": {"properties": {"mode": {"type": "string", "pattern": "^(reschedule|force_terminate)$", "title": "Mode", "default": "reschedule"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "_DrainBody"}, "_LoginRequest": {"properties": {"email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Email"}, "password": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Password"}}, "type": "object", "title": "_LoginRequest"}, "_NodeRegister": {"properties": {"hostname": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Hostname"}, "region": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Region"}, "cpu": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Mem Gb"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, "type": "object", "required": ["hostname"], "title": "_NodeRegister"}, "_RRReject": {"properties": {"reason": {"type": "string", "title": "Reason"}}, "type": "object", "required": ["reason"], "title": "_RRReject"}, "_SignupRequest": {"properties": {"email": {"type": "string", "maxLength": 254, "minLength": 3, "title": "Email"}, "name": {"type": "string", "maxLength": 100, "minLength": 1, "title": "Name"}, "password": {"type": "string", "maxLength": 128, "minLength": 8, "title": "Password"}}, "type": "object", "required": ["email", "name", "password"], "title": "_SignupRequest"}, "app__api__schemas__node_pool__PoolCreate": {"properties": {"cluster_id": {"type": "string", "title": "Cluster Id"}, "name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "description": {"anyOf": [{"type": "string", "maxLength": 1000}, {"type": "null"}], "title": "Description"}, "kind": {"type": "string", "pattern": "^(shared|dedicated)$", "title": "Kind", "default": "dedicated"}}, "type": "object", "required": ["cluster_id", "name"], "title": "PoolCreate"}, "app__api__storage_pools_router__PoolCreate": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80, "minLength": 1}, {"type": "null"}], "title": "Name"}, "cluster_id": {"type": "string", "title": "Cluster Id"}, "storage_class": {"type": "string", "maxLength": 200, "minLength": 1, "title": "Storage Class"}, "node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}, "share_scope": {"type": "string", "pattern": "^(all|selected)$", "title": "Share Scope", "default": "all"}, "shared_with": {"items": {"type": "string"}, "type": "array", "title": "Shared With", "default": []}, "manual_capacity_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Manual Capacity Gb"}}, "type": "object", "required": ["cluster_id", "storage_class"], "title": "PoolCreate"}}}} +{"openapi": "3.1.0", "info": {"title": "gShare API", "version": "v1"}, "paths": {"/api/v1/auth/me": {"get": {"tags": ["users"], "summary": "Auth Me", "description": "Return identity/role/memberships of the current principal.\n\nmemberships is returned as a list of {group_id, project_name, role} for the console's context\nswitcher and RBAC, converted from the internal {project_id: role} mapping with names resolved.", "operationId": "auth_me_api_v1_auth_me_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MeResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/auth/login": {"post": {"tags": ["users"], "summary": "Auth Login", "description": "Email+password local login (gated by AUTH_ALLOW_LOCAL_PASSWORD).\n\nLooks the user up by email and issues an HS256 token signed with USER_JWT_SECRET, which\njwt_auth.verify_jwt verifies.", "operationId": "auth_login_api_v1_auth_login_post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/_LoginRequest"}}}, "required": true}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/auth/signup": {"post": {"tags": ["users"], "summary": "Auth Signup", "description": "Self-service registration, governed by the sign-up policy in system settings.\n\n`closed` refuses outright; `open` creates a usable account; `approval` creates it as\n``pending``, which cannot sign in until an administrator approves it. Either way the account\nstarts with **no department** \u2014 an administrator assigns one at approval, or later. Until then\nthe account resolves to the global resource policy and has no group wallet to draw credits\nfrom, which is why the approval screen assigns a department in the same step.", "operationId": "auth_signup_api_v1_auth_signup_post", "requestBody": {"content": {"application/json": {"schema": {"$ref": "#/components/schemas/_SignupRequest"}}}, "required": true}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/approve": {"post": {"tags": ["users"], "summary": "Approve User", "description": "Approve a self-registered account: assign the department, activate, grant welcome credit.\n\nOne step rather than three, because a half-approved account (active, no department, no\ncredits) is a state nobody wants to find. super_admin, or an org_admin for a group of theirs.", "operationId": "approve_user_api_v1_users__user_id__approve_post", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserApproveBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/auth/change-password": {"post": {"tags": ["users"], "summary": "Change Password", "description": "Change your own password. Unless must_change_password is set, the current password is\nverified. A fresh token is issued afterwards.", "operationId": "change_password_api_v1_auth_change_password_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ChangePasswordRequest"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users": {"get": {"tags": ["users"], "summary": "List Users", "description": "Paginated user list. super_admin, org_admin, or group_admin, the latter two scoped to the\ngroups they administer.", "operationId": "list_users_api_v1_users_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "org_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}}, {"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["users"], "summary": "Create User", "description": "Create a user + enroll them into the chosen group with an initial membership role.\n\nThe new user is created in ``active`` (or ``suspended``) state; ``invited`` is reserved for the\ninvite-mail flow. A group is mandatory \u2014 the user joins it on creation (org is derived from the\ngroup). Email is UNIQUE (-> 409 conflict). super_admin\u00b7org_admin.", "operationId": "create_user_api_v1_users_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/bulk": {"post": {"tags": ["users"], "summary": "Bulk Create Users", "description": "Roster import: create up to 200 users per request, each with a personal wallet, a\nmembership in the chosen group, and a server-generated initial password returned once in the\nresponse (must_change_password forces rotation at first login).\n\nPartial success by design: rows report ``created`` / ``exists`` / ``invalid`` individually so\nre-uploading a roster is safe \u2014 existing accounts are reported, not fatal. The whole batch is\nidempotent on the Idempotency-Key (a replay returns the stored result, passwords included,\nfor 24h). One audit record per batch, not one per student. super_admin\u00b7org_admin.", "operationId": "bulk_create_users_api_v1_users_bulk_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkUserCreate"}}}}, "responses": {"207": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/resolve": {"get": {"tags": ["users"], "summary": "Resolve User", "description": "Resolve an EXACT email to {id, name} for the volume-share confirm step.\n\nAny authenticated user may call it: sharing needs \"does this address exist, and who is it\",\nand members cannot list users. Only an exact match answers \u2014 no enumeration surface beyond\nwhat grant-by-email already reveals.", "operationId": "resolve_user_api_v1_users_resolve_get", "parameters": [{"name": "email", "in": "query", "required": true, "schema": {"type": "string", "minLength": 3, "maxLength": 254, "title": "Email"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}": {"get": {"tags": ["users"], "summary": "Get User", "description": "User detail incl. memberships. self or super_admin/org_admin.", "operationId": "get_user_api_v1_users__user_id__get", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["users"], "summary": "Update User", "description": "Update a user. What may be changed depends on the caller's role.\n\n- super_admin: email, name, status, and password reset. Group membership has its own endpoint.\n- org_admin: password reset (and group) for users in their organization. Not email or name.\n- group_admin: password reset only, for users in their group.\n- The user themselves: their display name only.", "operationId": "update_user_api_v1_users__user_id__patch", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["users"], "summary": "Delete User", "description": "Deactivate (soft, default) or hard-delete a user.\n\nDefault = soft delete (``status=suspended`` + ``deleted_at``). ``?hard=true`` is\nsuper_admin-only and refused when a live session exists (ledger preservation -> 409 conflict).", "operationId": "delete_user_api_v1_users__user_id__delete", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "hard", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Hard"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/usage": {"get": {"tags": ["users"], "summary": "Get User Usage", "description": "Live resource footprint: sessions, host compute, GPU slices, volumes, wallet.\n\nSelf or an administrator (``user.read``). Everything is CURRENT state, not history \u2014 the\nadmin drawer answers \"what is this user holding right now?\".", "operationId": "get_user_usage_api_v1_users__user_id__usage_get", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/department": {"put": {"tags": ["users"], "summary": "Set User Department", "description": "Set, or move, a user's group. super_admin or org_admin.\n\n- super_admin: move to any group, or pass None to remove all group membership.\n- org_admin: move only within their own organization; memberships elsewhere are left alone.\n\nIf the user is not already in the target group they are added as a member, and their previous\ngroup memberships within the caller's scope are removed.", "operationId": "set_user_department_api_v1_users__user_id__department_put", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/UserDepartmentSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/users/{user_id}/global-role": {"put": {"tags": ["users"], "summary": "Set Global Role", "description": "Grant or revoke global roles; super_admin only. Several roles may be granted at once.", "operationId": "set_global_role_api_v1_users__user_id__global_role_put", "parameters": [{"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GlobalRoleSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations": {"get": {"tags": ["groups"], "summary": "List Organizations", "description": "List organizations. super_admin sees all; org_admin sees only their own (tenant\nisolation).", "operationId": "list_organizations_api_v1_organizations_get", "parameters": [{"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Create Organization", "description": "Create an organization. super_admin only.", "operationId": "create_organization_api_v1_organizations_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OrgCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations/{org_id}": {"get": {"tags": ["groups"], "summary": "Get Organization", "description": "Fetch one organization, for deep links from the edit and admin pages.", "operationId": "get_organization_api_v1_organizations__org_id__get", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["groups"], "summary": "Update Organization", "description": "Update an organization's name or status. super_admin only.", "operationId": "update_organization_api_v1_organizations__org_id__patch", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OrgUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["groups"], "summary": "Delete Organization", "description": "Soft-delete an organization. super_admin only; 409 while live groups remain, to avoid\norphans.", "operationId": "delete_organization_api_v1_organizations__org_id__delete", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations/{org_id}/admins": {"get": {"tags": ["groups"], "summary": "List Org Admins", "description": "List an organization's admins. super_admin, or an org_admin of that organization.", "operationId": "list_org_admins_api_v1_organizations__org_id__admins_get", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Add Org Admin", "description": "Appoint an organization admin. super_admin only.", "operationId": "add_org_admin_api_v1_organizations__org_id__admins_post", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OrgAdminCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/organizations/{org_id}/admins/{user_id}": {"delete": {"tags": ["groups"], "summary": "Remove Org Admin", "description": "Remove an organization admin. super_admin only.", "operationId": "remove_org_admin_api_v1_organizations__org_id__admins__user_id__delete", "parameters": [{"name": "org_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Org Id"}}, {"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects": {"get": {"tags": ["groups"], "summary": "List Projects", "description": "List groups. super_admin sees all; everyone else sees only the groups they belong to.", "operationId": "list_projects_api_v1_projects_get", "parameters": [{"name": "org_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Create Project", "description": "Create a group along with its default wallet. super_admin or org_admin.", "operationId": "create_project_api_v1_projects_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjectCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects/{group_id}": {"get": {"tags": ["groups"], "summary": "Get Project", "description": "Fetch one group, for deep links from the edit, admin, and delete pages.", "operationId": "get_project_api_v1_projects__group_id__get", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["groups"], "summary": "Update Project", "description": "Update a group's name or archived status. super_admin or group_admin.", "operationId": "update_project_api_v1_projects__group_id__patch", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ProjectPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["groups"], "summary": "Delete Project", "description": "Soft-delete a group. super_admin or org_admin; 409 while live sessions remain.\n\nMemberships are removed with it, so a soft-deleted group leaves no permissions behind. The\ngroup wallet is preserved.", "operationId": "delete_project_api_v1_projects__group_id__delete", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects/{group_id}/memberships": {"get": {"tags": ["groups"], "summary": "List Memberships", "description": "List a group's memberships. super_admin or group_admin.", "operationId": "list_memberships_api_v1_projects__group_id__memberships_get", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["groups"], "summary": "Add Membership", "description": "Add a member or grant a role. A guest must carry expires_at. super_admin or group_admin.", "operationId": "add_membership_api_v1_projects__group_id__memberships_post", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MembershipCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/projects/{group_id}/memberships/{membership_id}": {"patch": {"tags": ["groups"], "summary": "Update Membership", "description": "Change a member's role. Demoting the last admin returns 409. super_admin or group_admin.", "operationId": "update_membership_api_v1_projects__group_id__memberships__membership_id__patch", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "membership_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Membership Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MembershipPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["groups"], "summary": "Remove Membership", "description": "Remove a member. Removing the last admin returns 409. super_admin or group_admin.", "operationId": "remove_membership_api_v1_projects__group_id__memberships__membership_id__delete", "parameters": [{"name": "group_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Group Id"}}, {"name": "membership_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Membership Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets": {"get": {"tags": ["credits"], "summary": "List Wallets", "operationId": "list_wallets_api_v1_credits_wallets_get", "parameters": [{"name": "owner_type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Type"}}, {"name": "owner_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/WalletRead"}, "title": "Response List Wallets Api V1 Credits Wallets Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/me": {"get": {"tags": ["credits"], "summary": "My Wallet", "operationId": "my_wallet_api_v1_credits_wallets_me_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WalletRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}": {"get": {"tags": ["credits"], "summary": "Get Wallet", "operationId": "get_wallet_api_v1_credits_wallets__wallet_id__get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WalletRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/topup": {"post": {"tags": ["credits"], "summary": "Topup", "operationId": "topup_api_v1_credits_wallets__wallet_id__topup_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRequestBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/adjust": {"post": {"tags": ["credits"], "summary": "Adjust", "operationId": "adjust_api_v1_credits_wallets__wallet_id__adjust_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AdjustBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/transfer": {"post": {"tags": ["credits"], "summary": "Transfer", "operationId": "transfer_api_v1_credits_wallets__wallet_id__transfer_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TransferBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-scope": {"get": {"tags": ["credits"], "summary": "Allocation Scope", "description": "Return the pools the caller can allocate from, and each pool's targets, with names.\n\nAn org_admin gets their organization's wallet, whose children are that organization's groups; a\ngroup_admin gets their group's wallet, whose children are its members; a super_admin gets\neverything. The UI uses this to pick a pool, populate its targets, and toggle direction between\nallocate and reclaim.", "operationId": "allocation_scope_api_v1_credits_allocation_scope_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/refill-schedule": {"get": {"tags": ["credits"], "summary": "Get Refill Schedule", "description": "When the monthly refill fires: day-of-month and hour (KST). Defaults: day 1, 00:00.", "operationId": "get_refill_schedule_api_v1_credits_refill_schedule_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["credits"], "summary": "Set Refill Schedule", "description": "Set the refill day/hour. super_admin \u2014 the same authority that sets the monthly total.", "operationId": "set_refill_schedule_api_v1_credits_refill_schedule_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/RefillScheduleBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocate": {"post": {"tags": ["credits"], "summary": "Allocate", "description": "Allocate credits down the hierarchy (organization -> project -> user), or reclaim upwards.\nAn idempotency key is required.\n\n\"Within your allowance\" is enforced automatically by the source wallet's available balance, and\nexceeding it returns 402. Authorization is handled by _assert_can_allocate.", "operationId": "allocate_api_v1_credits_allocate_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AllocateBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/monthly-grant": {"post": {"tags": ["credits"], "summary": "Set Monthly Grant", "description": "Set a child wallet's monthly automatic refill, as the administrator one level up.\n\nThe siblings' grants must sum within the parent's grant; 0 disables refills for that wallet. The\nrefill itself \u2014 topping the balance up to the grant at the start of each month, never taking\na surplus away \u2014 is performed by the credit_refill worker.", "operationId": "set_monthly_grant_api_v1_credits_wallets__wallet_id__monthly_grant_post", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/MonthlyGrantBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WalletRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/bulk-allocate": {"post": {"tags": ["credits"], "summary": "Bulk Allocate", "description": "Allocate ``amount`` from the group's wallet to EVERY member's personal wallet at once.\n\nThe source balance is checked up front against n\u00d7amount (402 on shortfall \u2014 all or nothing,\nno partially funded cohort), and every per-wallet transaction carries an idempotency key\nderived from the batch key, so a replay after a crash completes exactly once per member.\ngroup_admin and above.", "operationId": "bulk_allocate_api_v1_credits_bulk_allocate_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkAllocateBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/bulk-monthly-grant": {"post": {"tags": ["credits"], "summary": "Bulk Monthly Grant", "description": "Set the same monthly refill on every member wallet of the group.\n\nThe ceiling check runs once for the whole cohort: n\u00d7amount must stay within the group\nwallet's own monthly grant (the same sibling-sum invariant set_monthly_grant enforces\nper wallet, without the O(n\u00b2) of calling it n times). Increases credit immediately, like\nthe single-wallet endpoint. group_admin and above.", "operationId": "bulk_monthly_grant_api_v1_credits_bulk_monthly_grant_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkMonthlyGrantBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-requests": {"post": {"tags": ["credits"], "summary": "Create Allocation Request", "description": "Create a credit allocation request, routed one level up: a user's goes to the group admin, a\ngroup's to the organization admin, an organization's to a super_admin.", "operationId": "create_allocation_request_api_v1_credits_allocation_requests_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AllocationRequestCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["credits"], "summary": "List Allocation Requests", "description": "box=mine lists the requests you raised; box=incoming lists pending requests you can\napprove; box=handled lists the decided ones from the same inbox \u2014 the approver's history.", "operationId": "list_allocation_requests_api_v1_credits_allocation_requests_get", "parameters": [{"name": "box", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(incoming|mine|handled)$", "default": "incoming", "title": "Box"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-requests/{request_id}/approve": {"post": {"tags": ["credits"], "summary": "Approve Allocation Request", "description": "Approve a request: allocate from the parent wallet to the target, or top the target up when\nthe parent is the system wallet. An insufficient pool returns 409, prompting escalation.", "operationId": "approve_allocation_request_api_v1_credits_allocation_requests__request_id__approve_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/allocation-requests/{request_id}/reject": {"post": {"tags": ["credits"], "summary": "Reject Allocation Request", "operationId": "reject_allocation_request_api_v1_credits_allocation_requests__request_id__reject_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AllocationRejectBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/spend-daily": {"get": {"tags": ["credits"], "summary": "Spend Daily", "description": "Daily spend (consume + storage) over [from, to], for the wallet's usage chart.\n\nAggregation happens here rather than over the paged ledger: a chart drawn from page one of the\ntransactions would silently truncate. Buckets follow the caller's clock via tz_offset_min\n(KST = +540), since \"a day\" on the chart is the user's day, not UTC's. Aggregated in Python so\nthe same query runs on Postgres and the SQLite test harness; the range is capped to a year.", "operationId": "spend_daily_api_v1_credits_wallets__wallet_id__spend_daily_get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "from", "in": "query", "required": true, "schema": {"type": "string", "format": "date", "title": "From"}}, {"name": "to", "in": "query", "required": true, "schema": {"type": "string", "format": "date", "title": "To"}}, {"name": "tz_offset_min", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 840, "minimum": -840, "default": 0, "title": "Tz Offset Min"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/SpendDayRead"}, "title": "Response Spend Daily Api V1 Credits Wallets Wallet Id Spend Daily Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/transactions": {"get": {"tags": ["credits"], "summary": "Transactions", "description": "The wallet ledger.\n\ngroup=\"session\" rolls the per-minute consume rows of one session into a single line (period,\ntotal, entry count); every other transaction type is a discrete event and passes through\nuntouched. Grouping happens in SQL because a long session produces hundreds of rows: folding\nthem client-side would only fold whatever landed on the current page.", "operationId": "transactions_api_v1_credits_wallets__wallet_id__transactions_get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "group", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(none|session)$", "default": "none", "title": "Group"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/TransactionRead"}, "title": "Response Transactions Api V1 Credits Wallets Wallet Id Transactions Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/wallets/{wallet_id}/holds": {"get": {"tags": ["credits"], "summary": "Holds", "description": "Active reservations + per-session settle status.\n\nReconstructed from the ledger: hold/consume/settle/refund txns are grouped by ``ref``\n(session id). A session with a hold but no settle is ``active``; otherwise ``settled``.", "operationId": "holds_api_v1_credits_wallets__wallet_id__holds_get", "parameters": [{"name": "wallet_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/topup-requests": {"post": {"tags": ["credits"], "summary": "Create Topup Request", "operationId": "create_topup_request_api_v1_credits_topup_requests_post", "parameters": [{"name": "wallet_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRequestBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["credits"], "summary": "List Topup Requests", "operationId": "list_topup_requests_api_v1_credits_topup_requests_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "wallet_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Id"}}, {"name": "scope", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(mine|all)$", "default": "mine", "title": "Scope"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRequestListResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/topup-requests/{request_id}/approve": {"post": {"tags": ["credits"], "summary": "Approve Topup Request", "operationId": "approve_topup_request_api_v1_credits_topup_requests__request_id__approve_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/credits/topup-requests/{request_id}/reject": {"post": {"tags": ["credits"], "summary": "Reject Topup Request", "operationId": "reject_topup_request_api_v1_credits_topup_requests__request_id__reject_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/TopupRejectBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/budgets": {"get": {"tags": ["budgets"], "summary": "List Budgets", "operationId": "list_budgets_api_v1_budgets_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "action", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/BudgetRead"}, "title": "Response List Budgets Api V1 Budgets Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["budgets"], "summary": "Create Budget", "operationId": "create_budget_api_v1_budgets_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/budgets/{budget_id}": {"get": {"tags": ["budgets"], "summary": "Get Budget", "operationId": "get_budget_api_v1_budgets__budget_id__get", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["budgets"], "summary": "Update Budget", "operationId": "update_budget_api_v1_budgets__budget_id__patch", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["budgets"], "summary": "Delete Budget", "operationId": "delete_budget_api_v1_budgets__budget_id__delete", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/budgets/{budget_id}/forecast": {"get": {"tags": ["budgets"], "summary": "Forecast", "description": "Project depletion from recent burn rate.\n\nburn_rate_per_day = consume over the lookback window / lookback days.\nprojected_depletion_at = now + remaining_credit / burn_rate_per_day.", "operationId": "forecast_api_v1_budgets__budget_id__forecast_get", "parameters": [{"name": "budget_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Budget Id"}}, {"name": "lookback", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(7d|14d|30d)$", "default": "7d", "title": "Lookback"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BudgetForecast"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/offerings": {"get": {"tags": ["offerings"], "summary": "List Offerings", "description": "Catalog list. Authenticated-but-open read; no admin gate.\n\nRetired (status=inactive) offerings are hidden from non-admins; administrators still see\nthem so they can reactivate or audit pricing.", "operationId": "list_offerings_api_v1_offerings_get", "parameters": [{"name": "gpu_model", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}}, {"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "default": "credit_per_hour", "title": "Sort"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["offerings"], "summary": "Create Offering", "operationId": "create_offering_api_v1_offerings_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OfferingCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/offerings/{offering_id}": {"get": {"tags": ["offerings"], "summary": "Get Offering", "description": "Fetch one offering, for deep links from the edit page. Readable by any authenticated\ncaller.", "operationId": "get_offering_api_v1_offerings__offering_id__get", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["offerings"], "summary": "Update Offering", "description": "Update offering; appends to price history on credit_per_hour change.", "operationId": "update_offering_api_v1_offerings__offering_id__patch", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OfferingUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["offerings"], "summary": "Delete Offering", "description": "Delete an offering; super_admin only. Rejected while a session still references it \u2014\ndeactivate it instead.", "operationId": "delete_offering_api_v1_offerings__offering_id__delete", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/offerings/{offering_id}/price-history": {"get": {"tags": ["offerings"], "summary": "Price History", "operationId": "price_history_api_v1_offerings__offering_id__price_history_get", "parameters": [{"name": "offering_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Offering Id"}}, {"name": "from", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "From"}}, {"name": "to", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "To"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-presets": {"get": {"tags": ["presets"], "summary": "List Presets", "operationId": "list_presets_api_v1_resource_presets_get", "parameters": [{"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "kind", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Kind"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["presets"], "summary": "Create Preset", "operationId": "create_preset_api_v1_resource_presets_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PresetCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-presets/{preset_id}": {"get": {"tags": ["presets"], "summary": "Get Preset", "description": "Fetch one preset, for deep links from the edit page.", "operationId": "get_preset_api_v1_resource_presets__preset_id__get", "parameters": [{"name": "preset_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Preset Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["presets"], "summary": "Update Preset", "description": "Update a preset; super_admin only. kind is immutable, and only the fields belonging to that\nkind are applied.", "operationId": "update_preset_api_v1_resource_presets__preset_id__patch", "parameters": [{"name": "preset_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Preset Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PresetUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["presets"], "summary": "Delete Preset", "description": "Delete a preset. Same authority as preset.create: super_admin.", "operationId": "delete_preset_api_v1_resource_presets__preset_id__delete", "parameters": [{"name": "preset_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Preset Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/effective": {"get": {"tags": ["policies"], "summary": "Effective Policy", "description": "The effective policy for the caller, with current usage and headroom, so the session wizard\ncan show the limits.\n\nResolution is the per-field merge in app.domain.policy (user \u2192 group \u2192 org \u2192 global), the\nsame module the admission gate uses. Caps are per user, so usage sums over the CALLER's\nactive sessions regardless of group.", "operationId": "effective_policy_api_v1_resource_policies_effective_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies": {"get": {"tags": ["policies"], "summary": "List Policies", "operationId": "list_policies_api_v1_resource_policies_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["policies"], "summary": "Create Policy", "operationId": "create_policy_api_v1_resource_policies_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PolicyCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/requests": {"post": {"tags": ["policies"], "summary": "Create Resource Request", "description": "Ask for a bigger compute quota. At least one target, all positive; note required.", "operationId": "create_resource_request_api_v1_resource_policies_requests_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ResourceRequestCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["policies"], "summary": "List Resource Requests", "operationId": "list_resource_requests_api_v1_resource_policies_requests_get", "parameters": [{"name": "box", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(mine|incoming)$", "default": "mine", "title": "Box"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/requests/{request_id}/approve": {"post": {"tags": ["policies"], "summary": "Approve Resource Request", "description": "Approve: upsert the requester's USER-scope policy with ONLY the granted limit keys.\n\nEverything not granted stays inherited (per-field most-specific merge), so the group/global\ndefaults remain the single source for the rest of the policy.", "operationId": "approve_resource_request_api_v1_resource_policies_requests__request_id__approve_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/requests/{request_id}/reject": {"post": {"tags": ["policies"], "summary": "Reject Resource Request", "operationId": "reject_resource_request_api_v1_resource_policies_requests__request_id__reject_post", "parameters": [{"name": "request_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Request Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_RRReject"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/resource-policies/{policy_id}": {"get": {"tags": ["policies"], "summary": "Get Policy", "description": "Fetch one policy, for deep links from the edit page.", "operationId": "get_policy_api_v1_resource_policies__policy_id__get", "parameters": [{"name": "policy_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Policy Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["policies"], "summary": "Update Policy", "operationId": "update_policy_api_v1_resource_policies__policy_id__patch", "parameters": [{"name": "policy_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Policy Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PolicyUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["policies"], "summary": "Delete Policy", "description": "Delete a resource policy. The global policy is super_admin only; the rest follow\npolicy.delete, which admits super_admin, org_admin, and group_admin.", "operationId": "delete_policy_api_v1_resource_policies__policy_id__delete", "parameters": [{"name": "policy_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Policy Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/preview-cost": {"post": {"tags": ["sessions"], "summary": "Preview Cost", "description": "Estimate cost without creating a session (pricing.estimate).\n\nestimated_credit_per_hour = offering.credit_per_hour * occupancy;\noccupancy = max(gpu_mem_mb/device_total_mem_mb, gpu_cores/100);\nhold_amount = estimated_credit_per_hour \u2014 admission reserves one hour up front.\nCPU (free) sessions are always 0.", "operationId": "preview_cost_api_v1_sessions_preview_cost_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PreviewCostRequest"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PreviewCostResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions": {"post": {"tags": ["sessions"], "summary": "Create Session", "description": "Admit a session through the scheduler gate. Idempotency-Key required.", "operationId": "create_session_api_v1_sessions_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}, {"name": "Idempotency-Key", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Idempotency-Key"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["sessions"], "summary": "List Sessions", "description": "List sessions, newest first, paginated.\n\nscope=\"mine\" (the default, backing the user's Sessions page) returns **only the caller's own\nsessions**, whatever their role. Administrators do not see other people's sessions on their\npersonal screen; that is what scope=all is for. scope=\"all\" (the administrators' session\nmonitoring screen) returns everything within the caller's authority: super_admin and org_admin\nsee all sessions, group_admin sees their own plus those of the groups they administer. A plain\nuser asking for scope=all is silently downgraded to their own sessions, so it cannot be used to\nescalate.", "operationId": "list_sessions_api_v1_sessions_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "scope", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(mine|all)$", "default": "mine", "title": "Scope"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/events": {"get": {"tags": ["sessions"], "summary": "Sessions Monitor Events", "description": "Admin session/queue monitor SSE stream.\n\nNOTE: this literal route MUST be declared before ``/sessions/{session_id}`` \u2014 otherwise the\nparameterized route captures ``/sessions/events`` (session_id=\"events\") and returns 404.", "operationId": "sessions_monitor_events_api_v1_sessions_events_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/gpu-availability": {"get": {"tags": ["sessions"], "summary": "Gpu Availability", "description": "Free GPU capacity per model, used by the session wizard to disable tiers. member and above.\n\nGroups the currently ready devices by model and returns each device's free memory, free cores,\nand mode. The console uses this to disable tiers that would not fit on a single card of the\nselected model, since the scheduler requires a fit on one device.\n\nThis is a literal path, so it must be declared before ``/sessions/{session_id}`` \u2014 the same\nreason the events route is.", "operationId": "gpu_availability_api_v1_sessions_gpu_availability_get", "parameters": [{"name": "fleet", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Fleet"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}": {"get": {"tags": ["sessions"], "summary": "Get Session", "description": "Fetch a single session (owner\u00b7admin).", "operationId": "get_session_api_v1_sessions__session_id__get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["sessions"], "summary": "Terminate Session", "description": "Terminate + settle.", "operationId": "terminate_session_api_v1_sessions__session_id__delete", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/start": {"post": {"tags": ["sessions"], "summary": "Start Session", "description": "Resume billing state machine.", "operationId": "start_session_api_v1_sessions__session_id__start_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/stop": {"post": {"tags": ["sessions"], "summary": "Stop Session", "description": "Stop (pause billing) + finalize remaining consume.", "operationId": "stop_session_api_v1_sessions__session_id__stop_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/restart": {"post": {"tags": ["sessions"], "summary": "Restart Session", "description": "Restart a session.", "operationId": "restart_session_api_v1_sessions__session_id__restart_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SessionRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/force-terminate": {"post": {"tags": ["sessions"], "summary": "Force Terminate", "description": "Admin force-terminate without owner consent. The free-text reason lands in the audit log;\nthe session's status_reason stays the typed `admin_stopped` the console maps to a message.", "operationId": "force_terminate_api_v1_sessions__session_id__force_terminate_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"$ref": "#/components/schemas/ForceTerminateBody"}, {"type": "null"}], "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/bulk-terminate": {"post": {"tags": ["sessions"], "summary": "Bulk Terminate", "description": "Force-terminate multiple sessions; per-target result array, idempotent.", "operationId": "bulk_terminate_api_v1_sessions_bulk_terminate_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BulkTerminateRequest"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/logs": {"get": {"tags": ["sessions"], "summary": "Session Logs", "description": "NOT IMPLEMENTED: nothing streams pod logs into this plane (the operator has no Redis\nproducer), so this always returned an empty list dressed up as a log. Honest 501 until a log\npipeline exists \u2014 use `kubectl logs` on the session pod meanwhile.", "operationId": "session_logs_api_v1_sessions__session_id__logs_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "tail", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 5000, "minimum": 1, "default": 200, "title": "Tail"}}, {"name": "stream", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(stdout|stderr|all)$", "default": "all", "title": "Stream"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/connections": {"get": {"tags": ["sessions"], "summary": "Session Connections", "description": "Issue one-time cnx_ connection tokens; `kind` narrows to one app (one token minted).", "operationId": "session_connections_api_v1_sessions__session_id__connections_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "kind", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "pattern": "^(vscode|jupyter|terminal)$"}, {"type": "null"}], "title": "Kind"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/ConnectionInfo"}, "title": "Response Session Connections Api V1 Sessions Session Id Connections Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/usage": {"get": {"tags": ["sessions"], "summary": "Session Usage Self", "description": "Measured live usage of the session's pod (owner\u00b7admin) \u2014 the detail page's meters.", "operationId": "session_usage_self_api_v1_sessions__session_id__usage_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/usage/live": {"get": {"tags": ["sessions"], "summary": "Session Usage Live", "description": "The last few minutes of one-second samples from the node agent (owner\u00b7admin).\n\nThis is the live view. It is deliberately separate from the Prometheus-backed series: that one\nis the record and covers GPU and history, this one answers \"is it running yet\" without waiting\nfor a scrape. `live` says whether an agent is actually reporting, so the console can show the\nslower series instead of a stale line when the DaemonSet is not deployed.", "operationId": "session_usage_live_api_v1_sessions__session_id__usage_live_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/usage/timeseries": {"get": {"tags": ["sessions"], "summary": "Session Usage Series Self", "description": "The usage metrics over a range (owner\u00b7admin) \u2014 the detail page's sparklines.", "operationId": "session_usage_series_self_api_v1_sessions__session_id__usage_timeseries_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "default": "15m", "title": "Range"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/timeline": {"get": {"tags": ["sessions"], "summary": "Session Timeline", "description": "Lifecycle timeline for the detail screen: created \u2192 queued/preparing \u2192 running \u2192 \u2026 with\nreasons, so an error state is readable from the log instead of a separate message box.", "operationId": "session_timeline_api_v1_sessions__session_id__timeline_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/checkpoints": {"post": {"tags": ["sessions"], "summary": "Create Checkpoint", "description": "NOT IMPLEMENTED: no worker or operator path takes a checkpoint yet \u2014 a row here would be\nan empty promise (storage_ref stays NULL forever). Honest 501 until the pipeline exists.", "operationId": "create_checkpoint_api_v1_sessions__session_id__checkpoints_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["sessions"], "summary": "List Checkpoints", "description": "List checkpoints for a session, newest first.", "operationId": "list_checkpoints_api_v1_sessions__session_id__checkpoints_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/checkpoints/{checkpoint_id}/restore": {"post": {"tags": ["sessions"], "summary": "Restore Checkpoint", "description": "NOT IMPLEMENTED: restore has no execution path (the operator's checkpointer states restore\nis intentionally unimplemented) \u2014 returning \"restoring\" here was a fabrication. Honest 501.", "operationId": "restore_checkpoint_api_v1_sessions__session_id__checkpoints__checkpoint_id__restore_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "checkpoint_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Checkpoint Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/sessions/{session_id}/events": {"get": {"tags": ["sessions"], "summary": "Session Events", "description": "Per-session SSE event stream.\n\nSubscribes to the session's status-change channel (Redis pub/sub fed by status_sync) and pushes\nstatus_changed / phase / allocation / heartbeat events. 404/403 are raised before the stream is\nestablished; the stream terminates cleanly on client disconnect.\n\nThe access check opens its own short-lived DB session: a Depends(get_db) session would stay\nchecked out of the pool for the whole stream (see get_sse_principal).", "operationId": "session_events_api_v1_sessions__session_id__events_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/queue": {"get": {"tags": ["queue"], "summary": "List Queue", "operationId": "list_queue_api_v1_queue_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/queue/mine": {"get": {"tags": ["queue"], "summary": "My Queue", "operationId": "my_queue_api_v1_queue_mine_get", "parameters": [{"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueueMineList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/queue/{queue_entry_id}": {"delete": {"tags": ["queue"], "summary": "Cancel Queue Entry", "description": "Cancel a queued entry; the session goes terminated and its hold is released.", "operationId": "cancel_queue_entry_api_v1_queue__queue_entry_id__delete", "parameters": [{"name": "queue_entry_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Queue Entry Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["queue"], "summary": "Update Priority", "description": "Admin reorders the queue: QueueEntry.priority sets the priority band.", "operationId": "update_priority_api_v1_queue__queue_entry_id__patch", "parameters": [{"name": "queue_entry_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Queue Entry Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/QueuePriorityPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes": {"get": {"tags": ["volumes"], "summary": "List Volumes", "description": "List volumes with scope/type/access_mode filters + pagination.\n\nDefault view is the caller's own world for every role \u2014 the user console must show a\nsuper_admin their volumes, not everyone's. `?all=true` (super_admin only) lists the fleet\nfor the admin volume page.", "operationId": "list_volumes_api_v1_storage_volumes_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}}, {"name": "access_mode", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Access Mode"}}, {"name": "all", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "All"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "array", "items": {"$ref": "#/components/schemas/VolumeRead"}, "title": "Response List Volumes Api V1 Storage Volumes Get"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["volumes"], "summary": "Create Volume", "description": "Create a named volume of any type.\n\nEvery type \u2014 personal workspace, group share, dataset, scratch \u2014 can be created as often as\nneeded and attached to sessions. There is no auto-provisioned singleton. Within a scope, the\n(type, name) pair is unique.", "operationId": "create_volume_api_v1_storage_volumes_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/quota-usage": {"get": {"tags": ["volumes"], "summary": "Storage Quota Usage", "description": "Per-scope storage limit, usage, and headroom, for the limit warning on the new-volume form.\n\nReads the same (scope, scope_id) policy and volume quota sum that _assert_storage_quota uses at\ncreation time. has_limit=false means unlimited: no policy, or a limit of 0.\n\nThe scope must be one the caller could create a volume in or belongs to: their own user scope,\na group they are a member of, or the global scope. Another tenant's limit and provisioned total\nare not theirs to read.", "operationId": "storage_quota_usage_api_v1_storage_volumes_quota_usage_get", "parameters": [{"name": "scope", "in": "query", "required": true, "schema": {"type": "string", "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": true, "schema": {"type": "string", "title": "Scope Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}": {"get": {"tags": ["volumes"], "summary": "Get Volume", "description": "Volume detail.", "operationId": "get_volume_api_v1_storage_volumes__volume_id__get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["volumes"], "summary": "Update Volume", "description": "Update volume meta: quota_gb / access_mode / mount_locked.\n\nThe quota only grows. Kubernetes never shrinks a claim, so a smaller ledger figure would free\npolicy headroom against space the pool still physically holds (100 GB \"shrunk\" to 10 GB plus a\nnew 90 GB volume = 190 GB on disk). An increase is bounded by the scope's storage policy \u2014\nvolumes are governed by the policy limit alone, not billed.", "operationId": "update_volume_api_v1_storage_volumes__volume_id__patch", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumePatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["volumes"], "summary": "Delete Volume", "description": "Permanently delete a volume; requires confirm==volume_id, rejects if mounted.\n\n``force`` (system administrator only) terminates every active session still mounting the\nvolume and then deletes it \u2014 the answer to a mount that keeps a shared volume alive against\nits owner's will. The audit row names the sessions that were cut off.", "operationId": "delete_volume_api_v1_storage_volumes__volume_id__delete", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "confirm", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Confirm"}}, {"name": "force", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Force"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/folders": {"get": {"tags": ["volumes"], "summary": "List Folders", "description": "List folders of a volume.", "operationId": "list_folders_api_v1_storage_volumes__volume_id__folders_get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["volumes"], "summary": "Create Folder", "description": "Create a folder (absolute path) under a volume.", "operationId": "create_folder_api_v1_storage_volumes__volume_id__folders_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Body"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/permissions": {"get": {"tags": ["volumes"], "summary": "List Permissions", "description": "List volume share permissions with user names.", "operationId": "list_permissions_api_v1_storage_volumes__volume_id__permissions_get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["volumes"], "summary": "Grant Permission", "description": "Grant/update a volume share permission; upsert on UNIQUE(volume_id,user_id).", "operationId": "grant_permission_api_v1_storage_volumes__volume_id__permissions_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PermissionBody"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/permissions/{user_id}": {"delete": {"tags": ["volumes"], "summary": "Revoke Permission", "description": "Revoke a share permission; refuse to remove the last owner.\n\nRemoving YOURSELF (leaving a share) is always allowed \u2014 a recipient's \"delete\" is an\nunshare, never a deletion of the original volume. Removing anyone else needs manage rights.", "operationId": "revoke_permission_api_v1_storage_volumes__volume_id__permissions__user_id__delete", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "user_id", "in": "path", "required": true, "schema": {"type": "string", "title": "User Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/snapshots": {"post": {"tags": ["volumes"], "summary": "Create Snapshot", "description": "NOT IMPLEMENTED: there is no CSI/storage integration behind snapshots \u2014 rows were being\nauto-flipped to ready by a timer without any data being copied. Honest 501 until a real\nsnapshot backend exists (blocked on the storage-backend decision).", "operationId": "create_snapshot_api_v1_storage_volumes__volume_id__snapshots_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"type": "object", "additionalProperties": true}, {"type": "null"}], "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["volumes"], "summary": "List Snapshots", "description": "List snapshots of a volume.", "operationId": "list_snapshots_api_v1_storage_volumes__volume_id__snapshots_get", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/snapshots/{snapshot_id}/restore": {"post": {"tags": ["volumes"], "summary": "Restore Snapshot", "description": "NOT IMPLEMENTED: restore performed no data operation (audit row + fabricated \"restoring\").\nHonest 501 until a real snapshot backend exists.", "operationId": "restore_snapshot_api_v1_storage_volumes__volume_id__snapshots__snapshot_id__restore_post", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "snapshot_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Snapshot Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"type": "object", "additionalProperties": true}, {"type": "null"}], "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/volumes/{volume_id}/snapshots/{snapshot_id}": {"delete": {"tags": ["volumes"], "summary": "Delete Snapshot", "description": "Delete a snapshot; reject while still creating.", "operationId": "delete_snapshot_api_v1_storage_volumes__volume_id__snapshots__snapshot_id__delete", "parameters": [{"name": "volume_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Volume Id"}}, {"name": "snapshot_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Snapshot Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/pools": {"get": {"tags": ["storage"], "summary": "List Pools", "description": "Every registered pool; `cluster_id` narrows to the ones that cluster may use.", "operationId": "list_pools_api_v1_storage_pools_get", "parameters": [{"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["storage"], "summary": "Create Pool", "description": "Register a pool. Capacity is left empty: the operator's next tick measures it.", "operationId": "create_pool_api_v1_storage_pools_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/app__api__storage_pools_router__PoolCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/storage/pools/{pool_id}": {"patch": {"tags": ["storage"], "summary": "Update Pool", "operationId": "update_pool_api_v1_storage_pools__pool_id__patch", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["storage"], "summary": "Delete Pool", "description": "Deregister a pool. Nothing on the storage server is touched \u2014 this only stops gShare\ncounting it; the volumes already on it keep working through their StorageClass.", "operationId": "delete_pool_api_v1_storage_pools__pool_id__delete", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters/summary": {"get": {"tags": ["clusters"], "summary": "Cluster Summary", "description": "The clusters a signed-in user can name: id, name and status only. The console's cluster\nselector (hidden while there is one) and the session wizard's cluster choice read this; the\nfull list with kubeconfig references stays super_admin-only.", "operationId": "cluster_summary_api_v1_clusters_summary_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters": {"get": {"tags": ["clusters"], "summary": "List Clusters", "description": "Cluster list. super_admin only.", "operationId": "list_clusters_api_v1_clusters_get", "parameters": [{"name": "role", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}}, {"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["clusters"], "summary": "Register Cluster", "description": "Register a cluster: validate kubeconfig, store secret ref, seed inventory.", "operationId": "register_cluster_api_v1_clusters_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterRegister"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters/{cluster_id}": {"get": {"tags": ["clusters"], "summary": "Get Cluster", "description": "Cluster detail + node/device summary. super_admin only.", "operationId": "get_cluster_api_v1_clusters__cluster_id__get", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["clusters"], "summary": "Update Cluster", "description": "Update name/role only. kubeconfig rotation is out of scope here. super_admin only.", "operationId": "update_cluster_api_v1_clusters__cluster_id__patch", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterPatch"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["clusters"], "summary": "Deregister Cluster", "description": "Deregister a cluster + discard its kubeconfig secret ref.\n\nRefused while live sessions/allocations exist on the cluster (-> 409). super_admin only.", "operationId": "deregister_cluster_api_v1_clusters__cluster_id__delete", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/clusters/{cluster_id}/connection-test": {"post": {"tags": ["clusters"], "summary": "Connection Test", "description": "Re-validate connectivity/health to the cluster apiserver.\n\nRe-runs the runtime/connectivity probe, applies the state-machine transition, and persists the\nnew ``status``. super_admin only.", "operationId": "connection_test_api_v1_clusters__cluster_id__connection_test_post", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/images": {"get": {"tags": ["images"], "summary": "List Images", "description": "List images/templates/ISOs with optional kind/q/tag/public filters. any authenticated.\n\n``public=true`` is what the session wizard uses, listing public images only. The administrative\ncatalog passes no filter and sees both public and private images.", "operationId": "list_images_api_v1_images_get", "parameters": [{"name": "kind", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Kind"}}, {"name": "q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Q"}}, {"name": "tag", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Tag"}}, {"name": "public", "in": "query", "required": false, "schema": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Public"}}, {"name": "mine", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Mine"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["images"], "summary": "Create Image", "description": "Register a catalog image referencing an existing registry path. super_admin\u00b7org_admin.", "operationId": "create_image_api_v1_images_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/images/{image_id}": {"get": {"tags": ["images"], "summary": "Get Image", "description": "Image detail. any authenticated, for the shared catalog and one's own images; another\nuser's private image answers 404 so its existence is not confirmed either.", "operationId": "get_image_api_v1_images__image_id__get", "parameters": [{"name": "image_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Image Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "patch": {"tags": ["images"], "summary": "Update Image", "description": "Update image metadata: public/private, name, CUDA version, supported GPUs. super_admin, gated\non image.create.", "operationId": "update_image_api_v1_images__image_id__patch", "parameters": [{"name": "image_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Image Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["images"], "summary": "Delete Image", "description": "Delete a catalog image that no session has ever used. super_admin, gated on image.create.\n\nSessions keep a foreign key to their image for the audit trail, so an image with any session\nhistory cannot be deleted \u2014 retire it instead by setting ``public: false``.\n\nOwners may delete their OWN built (private) images; everything else stays admin-gated.", "operationId": "delete_image_api_v1_images__image_id__delete", "parameters": [{"name": "image_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Image Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/images/import": {"post": {"tags": ["images"], "summary": "Import Image", "description": "Register an image from an external registry reference. any authenticated.\n\nRegistration is synchronous catalog metadata: the actual pull happens on the GPU node's\ncontainer runtime when a session using the image first starts (there is no control-plane pull\nworker). The row is therefore created ``import_status=ready`` immediately. Private-registry\ncredentials are not supported yet \u2014 imagePullSecrets plumbing does not exist \u2014 so a request\ncarrying ``registry_auth`` is refused rather than silently losing the credential.\n\nWho owns the row:\n\n* ``image.create`` holders (super_admin) register SHARED catalog entries \u2014 ``owner_user_id``\n null, ``public`` as given. Re-registering a ref that already exists as a shared row is a 409.\n* everyone else registers a PRIVATE row they own (``public=false``, ``kind=container``), which\n only they and admins can see. The same public ref may therefore be imported by many members.\n\nAlways answers 202. Deduplication never fails the request: re-importing your own ref, or a ref\nthat is already in the shared catalog, returns that row with ``existing: true`` instead of\ncreating a second one \u2014 the caller uses the returned ``id`` either way.", "operationId": "import_image_api_v1_images_import_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageImport"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/image-builds": {"post": {"tags": ["images"], "summary": "Create Build", "description": "Create a console image build: record desired state, then hand the GShareImageBuild CR to\nthe operator (which runs kaniko and reports back via /internal/image-builds/{id}/status).\n\nMembers build for themselves; the pushed image lands as a PRIVATE Image row\n(owner + admins only). One build in flight per user.", "operationId": "create_build_api_v1_image_builds_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BuildCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "get": {"tags": ["images"], "summary": "List Builds", "description": "List builds. member sees own-project builds; restricted to membership projects.", "operationId": "list_builds_api_v1_image_builds_get", "parameters": [{"name": "group_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, {"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "source", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Source"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ImageBuildList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/image-builds/{build_id}": {"get": {"tags": ["images"], "summary": "Get Build", "description": "Build detail incl. image_ref / scan summary.", "operationId": "get_build_api_v1_image_builds__build_id__get", "parameters": [{"name": "build_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Build Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/image-builds/{build_id}/logs": {"get": {"tags": ["images"], "summary": "Build Logs", "description": "Return the stored kaniko log tail (the operator reports the last ~16KB on each callback).", "operationId": "build_logs_api_v1_image_builds__build_id__logs_get", "parameters": [{"name": "build_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Build Id"}}, {"name": "tail", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 10000, "minimum": 1, "default": 500, "title": "Tail"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/events": {"get": {"tags": ["notifications"], "summary": "Notification Events", "description": "Live SSE stream of the caller's notifications: a ping event per new notification, which the\nconsole turns into a refetch of the list.\n\nEventSource cannot set headers, so authentication goes through ``?access_token=``, which\nget_current_principal accepts.", "operationId": "notification_events_api_v1_notifications_events_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications": {"get": {"tags": ["notifications"], "summary": "List Notifications", "description": "List the caller's own notifications, newest first. Self-scoped only.", "operationId": "list_notifications_api_v1_notifications_get", "parameters": [{"name": "unread", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Unread"}}, {"name": "include_deleted", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Include Deleted"}}, {"name": "type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "title": "Type"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["notifications"], "summary": "Delete All Notifications", "description": "Delete every notification of the caller. Self-scoped by construction.", "operationId": "delete_all_notifications_api_v1_notifications_delete", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/{notification_id}/read": {"post": {"tags": ["notifications"], "summary": "Mark Read", "description": "Mark one notification read; idempotent no-op if already read.", "operationId": "mark_read_api_v1_notifications__notification_id__read_post", "parameters": [{"name": "notification_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Notification Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/{notification_id}": {"delete": {"tags": ["notifications"], "summary": "Delete Notification", "description": "Delete one of the caller's notifications. 404 for other users' rows (no existence leak).", "operationId": "delete_notification_api_v1_notifications__notification_id__delete", "parameters": [{"name": "notification_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Notification Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/notifications/read-all": {"post": {"tags": ["notifications"], "summary": "Mark All Read", "description": "Bulk mark the caller's unread notifications read, optionally bounded.", "operationId": "mark_all_read_api_v1_notifications_read_all_post", "parameters": [{"name": "type", "in": "query", "required": false, "schema": {"anyOf": [{"type": "array", "items": {"type": "string"}}, {"type": "null"}], "title": "Type"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"content": {"application/json": {"schema": {"anyOf": [{"type": "object", "additionalProperties": true}, {"type": "null"}], "title": "Body"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/audit-logs/export": {"get": {"tags": ["audit"], "summary": "Export Audit Logs", "description": "The current audit view as a CSV file, newest first, same scope and filters as the list.\n\nUTF-8 with a BOM so Excel opens Korean names correctly; ``detail`` is the JSON blob verbatim.\nTaking the export is itself audited (``audit.export``, with the filters and the row count):\na file leaving the system is exactly the kind of event the log exists for.", "operationId": "export_audit_logs_api_v1_audit_logs_export_get", "parameters": [{"name": "actor_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Id"}}, {"name": "actor_q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Q"}}, {"name": "action", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}}, {"name": "target", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target"}}, {"name": "at[gte]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Gte]"}}, {"name": "at[lt]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Lt]"}}, {"name": "result", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Result"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/audit-logs": {"get": {"tags": ["audit"], "summary": "List Audit Logs", "operationId": "list_audit_logs_api_v1_audit_logs_get", "parameters": [{"name": "actor_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Id"}}, {"name": "actor_q", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Q"}}, {"name": "action", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}}, {"name": "target", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target"}}, {"name": "at[gte]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Gte]"}}, {"name": "at[lt]", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "At[Lt]"}}, {"name": "result", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Result"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "sort", "in": "query", "required": false, "schema": {"type": "string", "default": "-at", "title": "Sort"}}, {"name": "verify", "in": "query", "required": false, "schema": {"type": "boolean", "default": false, "title": "Verify"}}, {"name": "page", "in": "query", "required": false, "schema": {"type": "integer", "minimum": 1, "default": 1, "title": "Page"}}, {"name": "size", "in": "query", "required": false, "schema": {"type": "integer", "maximum": 100, "minimum": 1, "default": 20, "title": "Size"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AuditLogList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/webhooks": {"get": {"tags": ["webhooks"], "summary": "List Webhooks", "operationId": "list_webhooks_api_v1_webhooks_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["webhooks"], "summary": "Create Webhook", "operationId": "create_webhook_api_v1_webhooks_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/WebhookCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/webhooks/{webhook_id}": {"delete": {"tags": ["webhooks"], "summary": "Delete Webhook", "operationId": "delete_webhook_api_v1_webhooks__webhook_id__delete", "parameters": [{"name": "webhook_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Webhook Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/dashboard/summary": {"get": {"tags": ["dashboard"], "summary": "Dashboard Summary", "operationId": "dashboard_summary_api_v1_dashboard_summary_get", "parameters": [{"name": "scope", "in": "query", "required": false, "schema": {"enum": ["mine", "managed"], "type": "string", "default": "mine", "title": "Scope"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/DashboardSummary"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes": {"get": {"tags": ["infra"], "summary": "List Nodes", "description": "Nodes, optionally narrowed to one cluster.\n\nThe console filtered this list in the browser, which meant every screen fetched every\ncluster's nodes to show one cluster's. `GpuNode.cluster_id` is indexed; the filter belongs here.", "operationId": "list_nodes_api_v1_nodes_get", "parameters": [{"name": "status", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, {"name": "region", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Region"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NodeList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["infra"], "summary": "Register Node", "description": "Register a node, initially offline. super_admin only.\n\nWithout a cluster_id the node is attached to the only registered cluster, which covers test and\nsingle-cluster setups. With several clusters the field is required.", "operationId": "register_node_api_v1_nodes_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_NodeRegister"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}": {"get": {"tags": ["infra"], "summary": "Get Node", "description": "Fetch one node, for deep links from the drain and device pages.", "operationId": "get_node_api_v1_nodes__node_id__get", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["infra"], "summary": "Delete Node", "description": "Decommission a node: clear its inventory and have the operator remove it from Kubernetes.\n\nsuper_admin only. Two phases, because the control plane never calls the workload Kubernetes\nAPI itself. This request clears the cards and marks the node ``decommissioning``; the operator\ndeletes the Node object on its next pass and reports back, and only then does the row go. That\nis what stops a removed node from reappearing: while the Node object exists, every inventory\nreport recreates the row (upsert by cluster + hostname), which is exactly what a manual\n`kubectl delete node` used to be needed for.\n\nRefuses while the node still carries live work \u2014 a live allocation on one of its cards, or a\nnon-terminal session the operator placed there \u2014 so removal can never strand a running\nsession's ledger. Ended allocations keep their history: the row survives with device_id NULL\nand its gpu_uuid intact, since the card it names no longer exists.\n\nRefuses while the node is still up: deleting a live node's object only makes its kubelet\nregister again seconds later. Drain it and power it down first.", "operationId": "delete_node_api_v1_nodes__node_id__delete", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}/cordon": {"post": {"tags": ["infra"], "summary": "Cordon Node", "description": "Cordon or uncordon a node. super_admin only.\n\ncordon=true blocks new scheduling (status=cordoned); false restores it (status=ready). Sessions\nalready running are left alone.", "operationId": "cordon_node_api_v1_nodes__node_id__cordon_post", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_CordonBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}/drain": {"post": {"tags": ["infra"], "summary": "Drain Node", "description": "Drain a node. super_admin only.\n\nBoth modes cordon FIRST (no new placements can land back), then act on every session holding\na live allocation on the node's devices:\n - reschedule: pause \u2192 resume each running/preparing session. Resume re-runs placement,\n which excludes cordoned nodes \u2014 the session comes back on another eligible card (same\n GPU model, enough VRAM/cores, pool access). No capacity \u21d2 the session stays PAUSED\n (\"parked\"): work preserved, owner can resume later.\n - force_terminate: terminate each affected session (settled like an admin stop).", "operationId": "drain_node_api_v1_nodes__node_id__drain_post", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_DrainBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools": {"get": {"tags": ["infra"], "summary": "List Node Pools", "description": "List node pools. An org_admin sees only the pools carrying a grant for one of their\norganizations (or a group in them).", "operationId": "list_node_pools_api_v1_node_pools_get", "parameters": [{"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "post": {"tags": ["infra"], "summary": "Create Node Pool", "operationId": "create_node_pool_api_v1_node_pools_post", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/app__api__schemas__node_pool__PoolCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools/{pool_id}": {"patch": {"tags": ["infra"], "summary": "Update Node Pool", "operationId": "update_node_pool_api_v1_node_pools__pool_id__patch", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolRead"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "delete": {"tags": ["infra"], "summary": "Delete Node Pool", "description": "Delete a pool: its nodes become shared (pool_id NULL) and its grants go with it. Refused\nwhile any live session holds an allocation on one of its nodes \u2014 cordon and drain first.", "operationId": "delete_node_pool_api_v1_node_pools__pool_id__delete", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/nodes/{node_id}/pool": {"put": {"tags": ["infra"], "summary": "Set Node Pool", "description": "Move a node into a pool (or back to shared with pool_id null). The pool must be in the\nnode's cluster. Sessions already on the node are left alone; only new placements change.", "operationId": "set_node_pool_api_v1_nodes__node_id__pool_put", "parameters": [{"name": "node_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Node Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/NodePoolSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools/{pool_id}/grants": {"post": {"tags": ["infra"], "summary": "Grant Node Pool", "description": "Grant a pool to an organization or group. super_admin: anything (the target must exist).\norg_admin: only sub-assignment of a pool already granted to their organization, to a group in\nthat organization (domain.node_pools.assert_may_grant).", "operationId": "grant_node_pool_api_v1_node_pools__pool_id__grants_post", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolGrantCreate"}}}}, "responses": {"201": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/node-pools/{pool_id}/grants/{grant_id}": {"delete": {"tags": ["infra"], "summary": "Revoke Node Pool Grant", "description": "Revoke a grant. Same rule as granting: an org_admin may only remove group grants inside an\norganization the pool is granted to.", "operationId": "revoke_node_pool_grant_api_v1_node_pools__pool_id__grants__grant_id__delete", "parameters": [{"name": "pool_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Pool Id"}}, {"name": "grant_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Grant Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"204": {"description": "Successful Response"}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices": {"get": {"tags": ["infra"], "summary": "List Gpu Devices", "operationId": "list_gpu_devices_api_v1_gpu_devices_get", "parameters": [{"name": "node_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GpuDeviceList"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices/{device_id}/alias": {"put": {"tags": ["infra"], "summary": "Set Device Alias", "description": "Name a physical card. super_admin only.\n\nThe console otherwise numbers cards by their position in the list, so \"card #2\" means a\ndifferent card the day a card is added or removed. An alias pins a name to the UUID. Unique\nwithin the cluster; the ledger owns it and inventory reports never overwrite it.", "operationId": "set_device_alias_api_v1_gpu_devices__device_id__alias_put", "parameters": [{"name": "device_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Device Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_DeviceAliasBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices/{device_id}/health": {"put": {"tags": ["infra"], "summary": "Set Device Health", "description": "Take one card out of service (or put it back). super_admin only.\n\n``unhealthy`` removes the card from placement and ends every session bound to it with\n``gpu_fault`` \u2014 a process whose CUDA context died cannot be resumed, so the honest outcome is\na settled session and a notified owner, not a running one that bills. ``ready`` puts the\ncard back after repair. The same routine serves operator health events that name a card.", "operationId": "set_device_health_api_v1_gpu_devices__device_id__health_put", "parameters": [{"name": "device_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Device Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/_DeviceHealthBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-devices/{device_id}/mode": {"put": {"tags": ["infra"], "summary": "Set Gpu Device Mode", "description": "Set a card's target pool (per-CARD, not per-node). super_admin, same tier as cordon.\n\nfractional\u2194exclusive is a metadata change applied as soon as the card is empty; \u2194mig also\nneeds the node-side geometry change, executed by the drain state machine (the card stops\naccepting placements immediately and flips when its last allocation ends).", "operationId": "set_gpu_device_mode_api_v1_gpu_devices__device_id__mode_put", "parameters": [{"name": "device_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Device Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/GpuDeviceModeSet"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/gpu-pools/{cluster_id}": {"put": {"tags": ["infra"], "summary": "Set Pool Targets", "description": "Set the cluster's MIG/hami-core pool split by TARGET COUNT \u2014 the console's coarse control\n(simpler and safer than dragging individual cards). The emptiest eligible cards are chosen;\neach transition drains first and runs through the GpuModeChange machinery.", "operationId": "set_pool_targets_api_v1_gpu_pools__cluster_id__put", "parameters": [{"name": "cluster_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PoolTargetsBody"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/metrics/cluster": {"get": {"tags": ["infra"], "summary": "Metrics Cluster", "description": "Fleet figures, or one cluster's when `cluster_id` is given.\n\nWithout the filter the console showed a cluster's card grid beside fleet-wide totals \u2014 eight\nnodes and three cards while the panel below said one. Every aggregate here now narrows the\nsame way, so the numbers on one screen describe one thing.", "operationId": "metrics_cluster_api_v1_metrics_cluster_get", "parameters": [{"name": "region", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Region"}}, {"name": "cluster_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/ClusterMetrics"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/metrics/billing-report": {"get": {"tags": ["infra"], "summary": "Billing Report", "description": "Settlement and billing report: the credit ledger (consume, settle, topup) aggregated by a\ngroup_by key.\n\nConsumption and top-ups join CreditTransaction to CreditWallet and are attributed to the owner\n(organization, group, or user). gpu_hours is a best-effort sum of the occupancy hours of GPU\nsessions overlapping [from_, to].", "operationId": "billing_report_api_v1_metrics_billing_report_get", "parameters": [{"name": "scope", "in": "query", "required": true, "schema": {"type": "string", "pattern": "^(org|group|wallet)$", "title": "Scope"}}, {"name": "scope_id", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Scope Id"}}, {"name": "from", "in": "query", "required": true, "schema": {"type": "string", "format": "date-time", "title": "From"}}, {"name": "to", "in": "query", "required": true, "schema": {"type": "string", "format": "date-time", "title": "To"}}, {"name": "group_by", "in": "query", "required": false, "schema": {"type": "string", "pattern": "^(group|offering|wallet)$", "default": "group", "title": "Group By"}}, {"name": "format", "in": "query", "required": false, "schema": {"type": "string", "default": "json", "title": "Format"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BillingReport"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/status": {"get": {"tags": ["monitoring"], "summary": "Monitoring Status", "description": "Whether the metrics backend answers, so the page can say \"not configured\" instead of\nrendering empty charts.", "operationId": "monitoring_status_api_v1_monitoring_status_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/sessions/{session_id}/usage": {"get": {"tags": ["monitoring"], "summary": "Session Usage", "description": "Measured live usage of ONE session's pod: cadvisor CPU/MEM + HAMi VRAM/GPU-core.\n\nInstant values for the monitor drawer, refreshed by the console. VRAM and core come from\nHAMi's in-container monitor, which only reports while a CUDA context exists \u2014 an idle\nnotebook legitimately reads 0 there while CPU/MEM still move.", "operationId": "session_usage_api_v1_monitoring_sessions__session_id__usage_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/sessions/{session_id}/usage/timeseries": {"get": {"tags": ["monitoring"], "summary": "Session Usage Timeseries", "description": "The four per-session usage metrics over a range, for the monitor detail sparklines. A\nfinished session gets its whole run instead of a trailing window.", "operationId": "session_usage_timeseries_api_v1_monitoring_sessions__session_id__usage_timeseries_get", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "default": "15m", "title": "Range"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/timeseries": {"get": {"tags": ["monitoring"], "summary": "Monitoring Timeseries", "description": "One panel over a time range. The panel id selects the query; the console never sends PromQL.", "operationId": "monitoring_timeseries_api_v1_monitoring_timeseries_get", "parameters": [{"name": "panel", "in": "query", "required": true, "schema": {"type": "string", "title": "Panel"}}, {"name": "range", "in": "query", "required": false, "schema": {"type": "string", "default": "1h", "title": "Range"}}, {"name": "node", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node"}}, {"name": "gpu", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/instant": {"get": {"tags": ["monitoring"], "summary": "Monitoring Instant", "description": "Current value per series \u2014 the snapshot table and the tiles.", "operationId": "monitoring_instant_api_v1_monitoring_instant_get", "parameters": [{"name": "panel", "in": "query", "required": true, "schema": {"type": "string", "title": "Panel"}}, {"name": "node", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node"}}, {"name": "gpu", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu"}}, {"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/monitoring/gpu-inventory": {"get": {"tags": ["monitoring"], "summary": "Monitoring Gpu Inventory", "description": "The ledger's view of each card: mode, allocated VRAM/cores, and the sessions holding it.\n\nDCGM cannot attribute a shared card's usage to a session (HAMi splits below its visibility), so\nsession attribution comes from the control plane instead of being guessed from metrics.", "operationId": "monitoring_gpu_inventory_api_v1_monitoring_gpu_inventory_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/system/branding": {"get": {"tags": ["system"], "summary": "Get Branding", "description": "Public: the sign-in screen renders this before anyone has a token.", "operationId": "get_branding_api_v1_system_branding_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BrandingOut"}}}}}}, "put": {"tags": ["system"], "summary": "Set Branding", "description": "Set the service name and logo; super_admin only.", "operationId": "set_branding_api_v1_system_branding_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BrandingUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BrandingOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/system/signup": {"get": {"tags": ["system"], "summary": "Get Signup Policy", "description": "Public: the sign-in screen shows its sign-up tab only when this is not `closed`.", "operationId": "get_signup_policy_api_v1_system_signup_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SignupPolicyOut"}}}}}}, "put": {"tags": ["system"], "summary": "Set Signup Policy", "description": "Set the sign-up policy; super_admin only.", "operationId": "set_signup_policy_api_v1_system_signup_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SignupPolicyUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/SignupPolicyOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/api/v1/system/placement": {"get": {"tags": ["system"], "summary": "Get Placement", "description": "The fractional-slice placement policy. Readable by anyone who may see the admin console.", "operationId": "get_placement_api_v1_system_placement_get", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlacementOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}, "put": {"tags": ["system"], "summary": "Set Placement", "description": "Set the placement policy. Applies to the next reservation; running sessions do not move.", "operationId": "set_placement_api_v1_system_placement_put", "parameters": [{"name": "access_token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)", "title": "Access Token"}, "description": "Token fallback for clients that cannot set custom headers, such as EventSource (SSE)"}, {"name": "authorization", "in": "header", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "description": "Bearer ", "title": "Authorization"}, "description": "Bearer "}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlacementUpdate"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/PlacementOut"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/sessions/{session_id}/status": {"post": {"tags": ["internal"], "summary": "Report Status", "operationId": "report_status_internal_sessions__session_id__status_post", "parameters": [{"name": "session_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Session Id"}}, {"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorStatusEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/image-builds/{build_id}/status": {"post": {"tags": ["internal"], "summary": "Report Build Status", "operationId": "report_build_status_internal_image_builds__build_id__status_post", "parameters": [{"name": "build_id", "in": "path", "required": true, "schema": {"type": "string", "title": "Build Id"}}, {"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/BuildStatusEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/connect/verify": {"get": {"tags": ["internal"], "summary": "Connect Verify", "operationId": "connect_verify_internal_connect_verify_get", "parameters": [{"name": "token", "in": "query", "required": false, "schema": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Token"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/audit/operator": {"post": {"tags": ["internal"], "summary": "Audit Operator", "operationId": "audit_operator_internal_audit_operator_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorAuditEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/inventory/gpu-devices": {"post": {"tags": ["internal"], "summary": "Upsert Gpu Device", "operationId": "upsert_gpu_device_internal_inventory_gpu_devices_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorGpuDeviceUpsert"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/inventory/nodes": {"post": {"tags": ["internal"], "summary": "Upsert Node", "operationId": "upsert_node_internal_inventory_nodes_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorNodeUpsert"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/cordoned": {"get": {"tags": ["internal"], "summary": "Cordoned Nodes", "description": "Hostnames the ledger holds as cordoned, for the operator to mirror onto the Kubernetes\nnodes (spec.unschedulable). The control plane never touches Kubernetes itself; without this\nmirror a gShare cordon only steered the ledger's card placement and kube-scheduler could still\nput a CPU session \u2014 or a resumed one \u2014 straight back on a node being drained.", "operationId": "cordoned_nodes_internal_nodes_cordoned_get", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/decommissioning": {"get": {"tags": ["internal"], "summary": "Decommissioning Nodes", "description": "Hostnames an administrator asked to remove from the cluster.\n\nThe console's delete button clears the ledger and parks the node here; the operator deletes\nthe matching Node object and calls back below. Without that second step the Node object\nsurvives, every inventory pass recreates the row, and the node reappears in the console \u2014\nwhich is why removing a node used to need a manual `kubectl delete node`.", "operationId": "decommissioning_nodes_internal_nodes_decommissioning_get", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/decommissioned": {"post": {"tags": ["internal"], "summary": "Node Decommissioned", "description": "The operator confirms the Node object is gone; the ledger row goes with it.", "operationId": "node_decommissioned_internal_nodes_decommissioned_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/inventory/drift": {"post": {"tags": ["internal"], "summary": "Report Drift", "operationId": "report_drift_internal_inventory_drift_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Body"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/nodes/health-events": {"post": {"tags": ["internal"], "summary": "Node Health Event", "description": "Record a NodeHealthEvent and, on a cordon action, mark GpuNode.status=cordoned.\n\nThe operator already cordoned the K8s node; the ledger reflects it so the console/scheduler\nstop placing new sessions there.\n\nThe operator's HealthReconciler addresses the node by its Kubernetes NAME (the hostname): it\nhas no ledger id. The row is therefore resolved by (token cluster, hostname) \u2014 with the ledger\nid still accepted for older callers \u2014 and the event carries the row's id, which the FK needs.\nLooking the hostname up as an id never matched: the cordon never reached the ledger and the\nevent insert violated the FK on Postgres.", "operationId": "node_health_event_internal_nodes_health_events_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorNodeHealthEvent"}}}}, "responses": {"202": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/.well-known/gshare-internal-jwks.json": {"get": {"tags": ["internal"], "summary": "Internal Jwks", "operationId": "internal_jwks__well_known_gshare_internal_jwks_json_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}}}, "/internal/volumes/sync": {"post": {"tags": ["internal"], "summary": "Sync Volumes", "operationId": "sync_volumes_internal_volumes_sync_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/OperatorVolumeSync"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/VolumeSyncResponse"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/internal/metrics/session-samples": {"post": {"tags": ["internal"], "summary": "Ingest Session Samples", "description": "Accept one node's batch of session samples.\n\nThe agent knows a session only by its CR name (the pod label), so the ids are resolved here \u2014\nthe same lower/underscore mapping the CR builder uses. An unknown name is dropped rather than\nstored under a key nothing will ever read.", "operationId": "ingest_session_samples_internal_metrics_session_samples_post", "parameters": [{"name": "authorization", "in": "header", "required": true, "schema": {"type": "string", "title": "Authorization"}}], "requestBody": {"required": true, "content": {"application/json": {"schema": {"$ref": "#/components/schemas/AgentReport"}}}}, "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {"type": "object", "additionalProperties": true, "title": "Response Ingest Session Samples Internal Metrics Session Samples Post"}}}}, "422": {"description": "Validation Error", "content": {"application/json": {"schema": {"$ref": "#/components/schemas/HTTPValidationError"}}}}}}}, "/healthz": {"get": {"tags": ["health"], "summary": "Healthz", "operationId": "healthz_healthz_get", "responses": {"200": {"description": "Successful Response", "content": {"application/json": {"schema": {}}}}}}}}, "components": {"schemas": {"AdjustBody": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "minimum": -1000000000000.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "reason": {"type": "string", "title": "Reason"}}, "type": "object", "required": ["amount", "reason"], "title": "AdjustBody"}, "AgentReport": {"properties": {"node": {"type": "string", "title": "Node"}, "samples": {"items": {"$ref": "#/components/schemas/AgentSample"}, "type": "array", "maxItems": 500, "title": "Samples"}}, "type": "object", "required": ["node"], "title": "AgentReport"}, "AgentSample": {"properties": {"session": {"type": "string", "title": "Session"}, "at": {"type": "number", "title": "At"}, "cpu_cores": {"type": "number", "minimum": 0.0, "title": "Cpu Cores"}, "mem_bytes": {"type": "integer", "minimum": 0.0, "title": "Mem Bytes"}}, "type": "object", "required": ["session", "at", "cpu_cores", "mem_bytes"], "title": "AgentSample"}, "AllocateBody": {"properties": {"from_wallet_id": {"type": "string", "title": "From Wallet Id"}, "to_wallet_id": {"type": "string", "title": "To Wallet Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["from_wallet_id", "to_wallet_id", "amount"], "title": "AllocateBody"}, "AllocationRejectBody": {"properties": {"reason": {"type": "string", "title": "Reason"}}, "type": "object", "required": ["reason"], "title": "AllocationRejectBody"}, "AllocationRequestCreate": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "level": {"type": "string", "pattern": "^(user|group|org)$", "title": "Level", "default": "user"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}, "note": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Note"}}, "type": "object", "required": ["amount"], "title": "AllocationRequestCreate"}, "AuditChainResult": {"properties": {"ok": {"type": "boolean", "title": "Ok"}, "checked": {"type": "integer", "title": "Checked"}, "broken_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Broken At"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["ok", "checked"], "title": "AuditChainResult", "description": "Optional integrity attestation appended when ``verify=true``."}, "AuditLogEntry": {"properties": {"id": {"type": "string", "title": "Id"}, "actor_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Id"}, "action": {"type": "string", "title": "Action"}, "target": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target"}, "result": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Result"}, "detail": {"additionalProperties": true, "type": "object", "title": "Detail"}, "trace_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Trace Id"}, "prev_hash": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Prev Hash"}, "entry_hash": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Entry Hash"}, "at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "At"}, "actor_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Name"}, "actor_email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Actor Email"}, "target_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target Name"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, "type": "object", "required": ["id", "action", "detail"], "title": "AuditLogEntry", "description": "One audit-log row as projected by ``_audit_view`` (+ resolved actor_name)."}, "AuditLogList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/AuditLogEntry"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}, "names": {"additionalProperties": {"type": "string"}, "type": "object", "title": "Names", "default": {}}, "chain": {"anyOf": [{"$ref": "#/components/schemas/AuditChainResult"}, {"type": "null"}]}}, "type": "object", "required": ["data", "pagination"], "title": "AuditLogList", "description": "GET /audit-logs envelope (+ optional ``chain`` when verify=true)."}, "BillingReport": {"properties": {"rows": {"items": {"$ref": "#/components/schemas/BillingReportRow"}, "type": "array", "title": "Rows"}, "totals": {"additionalProperties": {"type": "string"}, "type": "object", "title": "Totals"}, "currency": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Currency"}}, "type": "object", "required": ["rows", "totals"], "title": "BillingReport"}, "BillingReportRow": {"properties": {"group": {"type": "string", "title": "Group"}, "group_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Name"}, "consumed": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Consumed"}, "topup": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Topup"}, "gpu_hours": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Hours"}}, "type": "object", "required": ["group"], "title": "BillingReportRow"}, "BoundSession": {"properties": {"session_id": {"type": "string", "title": "Session Id"}, "gpu_mem_mb": {"type": "integer", "title": "Gpu Mem Mb"}, "gpu_cores": {"type": "integer", "title": "Gpu Cores"}}, "type": "object", "required": ["session_id", "gpu_mem_mb", "gpu_cores"], "title": "BoundSession"}, "BrandingOut": {"properties": {"service_name": {"type": "string", "title": "Service Name"}, "logo": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Logo"}}, "type": "object", "required": ["service_name"], "title": "BrandingOut"}, "BrandingUpdate": {"properties": {"service_name": {"anyOf": [{"type": "string", "maxLength": 40, "minLength": 1}, {"type": "null"}], "title": "Service Name"}, "logo": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Logo"}, "clear_logo": {"type": "boolean", "title": "Clear Logo", "default": false}}, "type": "object", "title": "BrandingUpdate"}, "BudgetCreate": {"properties": {"scope": {"type": "string", "pattern": "^(org|group)$", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "period_start": {"type": "string", "format": "date-time", "title": "Period Start"}, "period": {"type": "string", "title": "Period", "default": "monthly"}, "limit_credit": {"anyOf": [{"type": "number", "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Limit Credit"}, "action": {"type": "string", "pattern": "^(alert|block)$", "title": "Action", "default": "alert"}}, "type": "object", "required": ["scope", "scope_id", "period_start", "limit_credit"], "title": "BudgetCreate"}, "BudgetForecast": {"properties": {"projected_exhaustion_date": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Projected Exhaustion Date"}, "burn_rate_per_day": {"type": "number", "title": "Burn Rate Per Day"}}, "type": "object", "required": ["burn_rate_per_day"], "title": "BudgetForecast"}, "BudgetRead": {"properties": {"id": {"type": "string", "title": "Id"}, "scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "limit_credit": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Limit Credit"}, "spent_credit": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Spent Credit"}, "action": {"type": "string", "title": "Action"}}, "type": "object", "required": ["id", "scope", "scope_id", "limit_credit", "spent_credit", "action"], "title": "BudgetRead"}, "BudgetUpdate": {"properties": {"limit_credit": {"anyOf": [{"type": "number", "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}, {"type": "null"}], "title": "Limit Credit"}, "action": {"anyOf": [{"type": "string", "pattern": "^(alert|block)$"}, {"type": "null"}], "title": "Action"}}, "type": "object", "title": "BudgetUpdate"}, "BuildCreate": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "source": {"type": "string", "title": "Source"}, "dockerfile": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Dockerfile"}, "git_url": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Git Url"}, "git_ref": {"type": "string", "title": "Git Ref", "default": "main"}, "context": {"type": "string", "title": "Context", "default": "."}, "build_args": {"additionalProperties": true, "type": "object", "title": "Build Args"}, "target_tag": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Target Tag"}}, "type": "object", "required": ["group_id", "name", "source"], "title": "BuildCreate"}, "BuildStatusEvent": {"properties": {"phase": {"type": "string", "title": "Phase"}, "image_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Ref"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "log_tail": {"anyOf": [{"type": "string", "maxLength": 32768}, {"type": "null"}], "title": "Log Tail"}}, "type": "object", "required": ["phase"], "title": "BuildStatusEvent"}, "BulkAllocateBody": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["group_id", "amount"], "title": "BulkAllocateBody"}, "BulkMonthlyGrantBody": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "minimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}}, "type": "object", "required": ["group_id", "amount"], "title": "BulkMonthlyGrantBody"}, "BulkTerminateRequest": {"properties": {"session_ids": {"items": {"type": "string"}, "type": "array", "title": "Session Ids"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["session_ids"], "title": "BulkTerminateRequest"}, "BulkUserCreate": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "initial_role": {"type": "string", "title": "Initial Role", "default": "member"}, "rows": {"items": {"$ref": "#/components/schemas/BulkUserRow"}, "type": "array", "maxItems": 200, "minItems": 1, "title": "Rows"}}, "type": "object", "required": ["group_id", "rows"], "title": "BulkUserCreate"}, "BulkUserRow": {"properties": {"email": {"type": "string", "maxLength": 254, "minLength": 3, "title": "Email"}, "name": {"type": "string", "maxLength": 100, "minLength": 1, "title": "Name"}}, "type": "object", "required": ["email", "name"], "title": "BulkUserRow"}, "ChangePasswordRequest": {"properties": {"current_password": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Current Password"}, "new_password": {"type": "string", "maxLength": 128, "minLength": 8, "title": "New Password"}}, "type": "object", "required": ["new_password"], "title": "ChangePasswordRequest"}, "ClusterCompute": {"properties": {"cpu": {"$ref": "#/components/schemas/ClusterResource"}, "mem_gb": {"$ref": "#/components/schemas/ClusterResource"}, "disk_gb": {"$ref": "#/components/schemas/ClusterResource"}}, "type": "object", "required": ["cpu", "mem_gb", "disk_gb"], "title": "ClusterCompute"}, "ClusterCredit": {"properties": {"consumed_last_24h": {"type": "string", "title": "Consumed Last 24H"}, "active_holds": {"type": "string", "title": "Active Holds"}}, "type": "object", "required": ["consumed_last_24h", "active_holds"], "title": "ClusterCredit"}, "ClusterGpu": {"properties": {"device_total": {"type": "integer", "title": "Device Total"}, "vram_total_mb": {"type": "integer", "title": "Vram Total Mb"}, "vram_used_mb": {"type": "integer", "title": "Vram Used Mb"}, "vram_load_pct": {"type": "number", "title": "Vram Load Pct"}, "avg_utilization_pct": {"type": "number", "title": "Avg Utilization Pct"}, "empty_gpu_count": {"type": "integer", "title": "Empty Gpu Count"}}, "type": "object", "required": ["device_total", "vram_total_mb", "vram_used_mb", "vram_load_pct", "avg_utilization_pct", "empty_gpu_count"], "title": "ClusterGpu"}, "ClusterList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/ClusterRead"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}}, "type": "object", "required": ["data", "pagination"], "title": "ClusterList", "description": "GET /clusters envelope."}, "ClusterMetrics": {"properties": {"as_of": {"type": "string", "title": "As Of"}, "nodes": {"$ref": "#/components/schemas/ClusterNodes"}, "gpu": {"$ref": "#/components/schemas/ClusterGpu"}, "sessions": {"$ref": "#/components/schemas/ClusterSessions"}, "credit": {"$ref": "#/components/schemas/ClusterCredit"}, "compute": {"$ref": "#/components/schemas/ClusterCompute"}, "storage": {"anyOf": [{"$ref": "#/components/schemas/ClusterStorage"}, {"type": "null"}]}}, "type": "object", "required": ["as_of", "nodes", "gpu", "sessions", "credit", "compute"], "title": "ClusterMetrics"}, "ClusterNodes": {"properties": {"total": {"type": "integer", "title": "Total"}, "ready": {"type": "integer", "title": "Ready"}, "busy": {"type": "integer", "title": "Busy"}, "cordoned": {"type": "integer", "title": "Cordoned"}, "offline": {"type": "integer", "title": "Offline"}}, "type": "object", "required": ["total", "ready", "busy", "cordoned", "offline"], "title": "ClusterNodes"}, "ClusterPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80, "minLength": 1}, {"type": "null"}], "title": "Name"}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}, "session_domain": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Domain"}}, "type": "object", "title": "ClusterPatch"}, "ClusterRead": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "role": {"type": "string", "title": "Role"}, "api_server": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Api Server"}, "runtime": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Runtime"}, "session_domain": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Domain"}, "status": {"type": "string", "title": "Status"}, "node_count": {"type": "integer", "title": "Node Count"}, "gpu_count": {"type": "integer", "title": "Gpu Count"}, "registered_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Registered At"}}, "type": "object", "required": ["id", "name", "role", "status", "node_count", "gpu_count"], "title": "ClusterRead", "description": "One cluster as projected by ``_serialize_cluster`` (list rows)."}, "ClusterRegister": {"properties": {"name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "role": {"type": "string", "title": "Role"}, "kubeconfig_b64": {"type": "string", "title": "Kubeconfig B64"}, "session_domain": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Domain"}}, "type": "object", "required": ["name", "role", "kubeconfig_b64"], "title": "ClusterRegister"}, "ClusterResource": {"properties": {"used": {"type": "integer", "title": "Used"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["used", "total"], "title": "ClusterResource", "description": "One host-compute dimension fleet-wide: promised to active sessions vs node capacity."}, "ClusterSessions": {"properties": {"running": {"type": "integer", "title": "Running"}, "queued": {"type": "integer", "title": "Queued"}}, "type": "object", "required": ["running", "queued"], "title": "ClusterSessions"}, "ClusterStorage": {"properties": {"disk_gb": {"$ref": "#/components/schemas/ClusterStorageDisk"}, "node_count": {"type": "integer", "title": "Node Count", "default": 0}, "capacity_gb": {"type": "integer", "title": "Capacity Gb", "default": 0}, "unplaced_gb": {"type": "integer", "title": "Unplaced Gb", "default": 0}, "shared": {"type": "boolean", "title": "Shared", "default": false}, "pools": {"items": {"$ref": "#/components/schemas/ClusterStoragePool"}, "type": "array", "title": "Pools", "default": []}}, "type": "object", "required": ["disk_gb"], "title": "ClusterStorage"}, "ClusterStorageDisk": {"properties": {"used": {"type": "integer", "title": "Used"}, "total": {"type": "integer", "title": "Total"}, "source": {"type": "string", "title": "Source", "default": "node_disk"}}, "type": "object", "required": ["used", "total"], "title": "ClusterStorageDisk"}, "ClusterStoragePool": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "hostname": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Hostname"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "storage_class": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Storage Class"}, "share_scope": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Share Scope"}, "capacity_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Capacity Gb"}, "capacity_source": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Capacity Source"}, "capacity_reported_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Capacity Reported At"}, "used_gb": {"type": "integer", "title": "Used Gb", "default": 0}}, "type": "object", "required": ["id"], "title": "ClusterStoragePool", "description": "One registered volume-backing pool: what it is, where it sits, and who may use it."}, "ConnectionInfo": {"properties": {"kind": {"type": "string", "title": "Kind"}, "url": {"type": "string", "title": "Url"}, "connection_token": {"type": "string", "title": "Connection Token"}, "expires_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Expires At"}, "command": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Command"}}, "type": "object", "required": ["kind", "url", "connection_token"], "title": "ConnectionInfo"}, "DashboardAllocation": {"properties": {"instances": {"$ref": "#/components/schemas/DashboardInstances"}, "vram": {"$ref": "#/components/schemas/MyVram"}, "gpu_cores": {"anyOf": [{"$ref": "#/components/schemas/ResourceUsage"}, {"type": "null"}]}}, "type": "object", "required": ["instances", "vram"], "title": "DashboardAllocation"}, "DashboardCompute": {"properties": {"cpu": {"$ref": "#/components/schemas/ResourceUsage"}, "mem_gb": {"$ref": "#/components/schemas/ResourceUsage"}, "disk_gb": {"$ref": "#/components/schemas/ResourceUsage"}}, "type": "object", "required": ["cpu", "mem_gb", "disk_gb"], "title": "DashboardCompute", "description": "Host compute held by the caller's active sessions \u2014 separate from GPU/credits, since\ncpu/mem/disk are quota-governed, not billed."}, "DashboardCredit": {"properties": {"available": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Available"}, "balance": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Balance"}, "reserved": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Reserved"}}, "type": "object", "title": "DashboardCredit", "description": "Owner wallet snapshot; all None when the user has no wallet."}, "DashboardInstances": {"properties": {"used": {"type": "integer", "title": "Used"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["used", "total"], "title": "DashboardInstances"}, "DashboardPool": {"properties": {"id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}, "name": {"type": "string", "title": "Name"}, "kind": {"type": "string", "title": "Kind"}, "tier": {"type": "string", "title": "Tier"}}, "type": "object", "required": ["name", "kind", "tier"], "title": "DashboardPool", "description": "A node pool the caller may place on. `id` is None for the unassigned (\"shared\") bucket."}, "DashboardRegion": {"properties": {"model": {"type": "string", "title": "Model"}, "total": {"type": "integer", "title": "Total"}, "free": {"type": "integer", "title": "Free"}, "free_mb": {"type": "integer", "title": "Free Mb", "default": 0}, "total_mb": {"type": "integer", "title": "Total Mb", "default": 0}}, "type": "object", "required": ["model", "total", "free"], "title": "DashboardRegion", "description": "Per-GPU-model availability bucket.\n\n`free`/`total` count whole cards, which under fractional sharing understates what is usable: a\ncard holding one small slice is not \"free\" yet can still host several more sessions. The VRAM\nfigures are what actually decide whether a session starts, so both are reported."}, "DashboardSessions": {"properties": {"running": {"type": "integer", "title": "Running"}, "active": {"type": "integer", "title": "Active"}}, "type": "object", "required": ["running", "active"], "title": "DashboardSessions"}, "DashboardSummary": {"properties": {"credit": {"$ref": "#/components/schemas/DashboardCredit"}, "sessions": {"$ref": "#/components/schemas/DashboardSessions"}, "vram": {"$ref": "#/components/schemas/DashboardVram"}, "regions": {"items": {"$ref": "#/components/schemas/DashboardRegion"}, "type": "array", "title": "Regions"}, "pools": {"items": {"$ref": "#/components/schemas/DashboardPool"}, "type": "array", "title": "Pools", "default": []}, "allocation": {"$ref": "#/components/schemas/DashboardAllocation"}, "compute": {"$ref": "#/components/schemas/DashboardCompute"}, "storage": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Storage"}}, "type": "object", "required": ["credit", "sessions", "vram", "regions", "allocation", "compute"], "title": "DashboardSummary", "description": "GET /dashboard/summary aggregate."}, "DashboardVram": {"properties": {"used_mb": {"type": "integer", "title": "Used Mb"}, "total_mb": {"type": "integer", "title": "Total Mb"}}, "type": "object", "required": ["used_mb", "total_mb"], "title": "DashboardVram"}, "ForceTerminateBody": {"properties": {"reason": {"anyOf": [{"type": "string", "maxLength": 500}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "ForceTerminateBody", "description": "Admin's justification \u2014 recorded verbatim in the audit log (the console requires it)."}, "GlobalRoleSet": {"properties": {"global_roles": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Global Roles"}, "global_role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Global Role"}}, "type": "object", "title": "GlobalRoleSet"}, "GpuDeviceList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/GpuDeviceRow"}, "type": "array", "title": "Data"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["data", "total"], "title": "GpuDeviceList"}, "GpuDeviceModeSet": {"properties": {"desired_mode": {"anyOf": [{"type": "string", "pattern": "^(fractional|exclusive|mig)$"}, {"type": "null"}], "title": "Desired Mode"}}, "type": "object", "title": "GpuDeviceModeSet"}, "GpuDeviceRow": {"properties": {"id": {"type": "string", "title": "Id"}, "node_id": {"type": "string", "title": "Node Id"}, "model": {"type": "string", "title": "Model"}, "alias": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Alias"}, "mode": {"type": "string", "title": "Mode"}, "desired_mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Desired Mode"}, "mode_state": {"type": "string", "title": "Mode State", "default": "ready"}, "status": {"type": "string", "title": "Status"}, "node_status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Status"}, "gpu_uuid": {"type": "string", "title": "Gpu Uuid"}, "total_mem_mb": {"type": "integer", "title": "Total Mem Mb"}, "used_mem_mb": {"type": "integer", "title": "Used Mem Mb"}, "free_mem_mb": {"type": "integer", "title": "Free Mem Mb"}, "total_cores": {"type": "integer", "title": "Total Cores"}, "used_cores": {"type": "integer", "title": "Used Cores"}, "free_cores": {"type": "integer", "title": "Free Cores"}, "bound_sessions": {"items": {"$ref": "#/components/schemas/BoundSession"}, "type": "array", "title": "Bound Sessions"}}, "type": "object", "required": ["id", "node_id", "model", "mode", "status", "gpu_uuid", "total_mem_mb", "used_mem_mb", "free_mem_mb", "total_cores", "used_cores", "free_cores", "bound_sessions"], "title": "GpuDeviceRow"}, "HTTPValidationError": {"properties": {"detail": {"items": {"$ref": "#/components/schemas/ValidationError"}, "type": "array", "title": "Detail"}}, "type": "object", "title": "HTTPValidationError"}, "ImageBuildList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/ImageBuildRead"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}}, "type": "object", "required": ["data", "pagination"], "title": "ImageBuildList", "description": "GET /image-builds envelope."}, "ImageBuildRead": {"properties": {"id": {"type": "string", "title": "Id"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "owner_user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner User Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "source": {"type": "string", "title": "Source"}, "status": {"type": "string", "title": "Status"}, "error": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Error"}, "image_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Ref"}, "image_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Id"}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "started_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Started At"}, "finished_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Finished At"}}, "type": "object", "required": ["id", "source", "status"], "title": "ImageBuildRead", "description": "One build row as projected by ``_serialize_build``."}, "ImageCreate": {"properties": {"name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "registry": {"type": "string", "title": "Registry"}, "kind": {"type": "string", "title": "Kind"}, "tags": {"additionalProperties": true, "type": "object", "title": "Tags"}, "supported_gpus": {"items": {"type": "string"}, "type": "array", "title": "Supported Gpus"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "gpu_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Gpu Ready"}}, "type": "object", "required": ["name", "registry", "kind"], "title": "ImageCreate"}, "ImageImport": {"properties": {"source_type": {"type": "string", "title": "Source Type"}, "source": {"type": "string", "title": "Source"}, "name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "kind": {"type": "string", "title": "Kind"}, "registry_auth": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Registry Auth"}, "tags": {"additionalProperties": true, "type": "object", "title": "Tags"}, "supported_gpus": {"items": {"type": "string"}, "type": "array", "title": "Supported Gpus"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "gpu_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Gpu Ready"}}, "type": "object", "required": ["source_type", "source", "name", "kind"], "title": "ImageImport"}, "ImageList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/ImageRead"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMeta"}}, "type": "object", "required": ["data", "pagination"], "title": "ImageList", "description": "GET /images envelope."}, "ImageRead": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"type": "string", "title": "Name"}, "registry": {"type": "string", "title": "Registry"}, "kind": {"type": "string", "title": "Kind"}, "tags": {"additionalProperties": true, "type": "object", "title": "Tags"}, "supported_gpus": {"items": {}, "type": "array", "title": "Supported Gpus"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "gpu_ready": {"type": "boolean", "title": "Gpu Ready", "default": false}, "public": {"type": "boolean", "title": "Public", "default": true}, "owner_user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner User Id"}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "import_status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Import Status"}}, "type": "object", "required": ["id", "name", "registry", "kind", "tags", "supported_gpus"], "title": "ImageRead", "description": "One catalog image as projected by ``_serialize_image``.\n\n``import_status`` is only present for imported/registered rows, so it is Optional."}, "ImageUpdate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "public": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Public"}, "registry": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Registry"}, "cuda_version": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cuda Version"}, "supported_gpus": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Supported Gpus"}, "gpu_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Gpu Ready"}}, "type": "object", "title": "ImageUpdate"}, "MeMembership": {"properties": {"group_id": {"type": "string", "title": "Group Id"}, "project_name": {"type": "string", "title": "Project Name"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}, "org_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Name"}, "role": {"type": "string", "title": "Role"}, "has_group_admin": {"type": "boolean", "title": "Has Group Admin", "default": true}}, "type": "object", "required": ["group_id", "project_name", "role"], "title": "MeMembership", "description": "One membership row resolved for the context switcher / RBAC."}, "MeResponse": {"properties": {"user_id": {"type": "string", "title": "User Id"}, "global_role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Global Role"}, "global_roles": {"items": {"type": "string"}, "type": "array", "title": "Global Roles", "default": []}, "org_admin_orgs": {"items": {"type": "string"}, "type": "array", "title": "Org Admin Orgs", "default": []}, "memberships": {"items": {"$ref": "#/components/schemas/MeMembership"}, "type": "array", "title": "Memberships"}, "email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Email"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "must_change_password": {"type": "boolean", "title": "Must Change Password"}}, "type": "object", "required": ["user_id", "memberships", "must_change_password"], "title": "MeResponse", "description": "Identity/role/memberships of the current principal (GET /auth/me)."}, "MembershipCreate": {"properties": {"user_id": {"type": "string", "title": "User Id"}, "role": {"type": "string", "title": "Role"}, "expires_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Expires At"}, "grant_credit": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Grant Credit"}}, "type": "object", "required": ["user_id", "role"], "title": "MembershipCreate"}, "MembershipPatch": {"properties": {"role": {"type": "string", "title": "Role"}}, "type": "object", "required": ["role"], "title": "MembershipPatch"}, "MonthlyGrantBody": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "minimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}}, "type": "object", "required": ["amount"], "title": "MonthlyGrantBody"}, "MyVram": {"properties": {"used_mb": {"type": "integer", "title": "Used Mb"}, "limit_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Limit Mb"}}, "type": "object", "required": ["used_mb"], "title": "MyVram", "description": "The caller's own VRAM footprint vs their policy limit (None = unlimited)."}, "NodeList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/NodeRow"}, "type": "array", "title": "Data"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["data", "total"], "title": "NodeList"}, "NodePoolSet": {"properties": {"pool_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Id"}}, "type": "object", "title": "NodePoolSet"}, "NodeRow": {"properties": {"id": {"type": "string", "title": "Id"}, "hostname": {"type": "string", "title": "Hostname"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "status": {"type": "string", "title": "Status"}, "cpu": {"type": "integer", "title": "Cpu"}, "mem_gb": {"type": "integer", "title": "Mem Gb"}, "disk_gb": {"type": "integer", "title": "Disk Gb", "default": 0}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}, "region": {"type": "string", "title": "Region"}, "gpu_mode": {"type": "string", "title": "Gpu Mode"}, "mode_counts": {"additionalProperties": {"type": "integer"}, "type": "object", "title": "Mode Counts", "default": {}}, "device_count": {"type": "integer", "title": "Device Count"}, "alloc_cpu": {"type": "integer", "title": "Alloc Cpu", "default": 0}, "alloc_mem_gb": {"type": "integer", "title": "Alloc Mem Gb", "default": 0}, "alloc_disk_gb": {"type": "integer", "title": "Alloc Disk Gb", "default": 0}, "running_sessions": {"type": "integer", "title": "Running Sessions", "default": 0}, "heartbeat_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Heartbeat At"}, "pool_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Id"}, "pool_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Name"}}, "type": "object", "required": ["id", "hostname", "status", "cpu", "mem_gb", "region", "gpu_mode", "device_count"], "title": "NodeRow"}, "OfferingCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "resource_class": {"type": "string", "title": "Resource Class", "default": "gpu"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "credit_per_hour": {"type": "string", "title": "Credit Per Hour"}, "status": {"type": "string", "title": "Status", "default": "active"}, "min_cuda": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Min Cuda"}}, "type": "object", "required": ["name", "credit_per_hour"], "title": "OfferingCreate"}, "OfferingUpdate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "credit_per_hour": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Credit Per Hour"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "min_cuda": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Min Cuda"}}, "type": "object", "title": "OfferingUpdate"}, "OperatorAuditEvent": {"properties": {"actor": {"type": "string", "title": "Actor"}, "action": {"type": "string", "title": "Action"}, "target": {"type": "string", "title": "Target"}, "result": {"type": "string", "title": "Result"}, "detail": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Detail"}, "trace_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Trace Id"}, "ts": {"type": "string", "format": "date-time", "title": "Ts"}}, "type": "object", "required": ["actor", "action", "target", "result", "ts"], "title": "OperatorAuditEvent", "description": "Operator privileged-action audit callback."}, "OperatorGpuDeviceUpsert": {"properties": {"node_id": {"type": "string", "title": "Node Id"}, "uuid": {"type": "string", "title": "Uuid"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}, "total_mem_mb": {"type": "integer", "title": "Total Mem Mb", "default": 0}, "used_mem_mb": {"type": "integer", "title": "Used Mem Mb", "default": 0}, "total_cores": {"type": "integer", "title": "Total Cores", "default": 0}, "used_cores": {"type": "integer", "title": "Used Cores", "default": 0}, "status": {"type": "string", "title": "Status", "default": "ready"}, "model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Model"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "node_cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Cpu"}, "node_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Node Ready"}, "node_mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Mem Gb"}, "node_disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Disk Gb"}}, "type": "object", "required": ["node_id", "uuid"], "title": "OperatorGpuDeviceUpsert", "description": "GPU device inventory upsert (operator InventoryReconciler -> ledger).\n\nPure reflection of measured device-plugin/DCGM capacity. The control plane preserves\nledger-owned occupancy (used_mem_mb/used_cores) \u2014 those are NOT overwritten from here."}, "OperatorNodeHealthEvent": {"properties": {"node_id": {"type": "string", "title": "Node Id"}, "kind": {"type": "string", "title": "Kind"}, "severity": {"type": "string", "title": "Severity", "default": "critical"}, "action": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Action"}, "gpu_uuid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Uuid"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Id"}}, "type": "object", "required": ["node_id", "kind"], "title": "OperatorNodeHealthEvent", "description": "Node health transition (operator HealthReconciler -> ledger).\n\nOn a critical breach (e.g. fatal Xid) the operator cordons the node and reports this; the\ncontrol plane records a NodeHealthEvent and marks GpuNode.status=cordoned."}, "OperatorNodeUpsert": {"properties": {"node_id": {"type": "string", "title": "Node Id"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "node_cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Cpu"}, "node_ready": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Node Ready"}, "node_mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Mem Gb"}, "node_disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Node Disk Gb"}, "lossless_capable": {"type": "boolean", "title": "Lossless Capable", "default": false}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}}, "type": "object", "required": ["node_id"], "title": "OperatorNodeUpsert", "description": "Upsert node inventory, reporting capacity for every node whether or not it has a GPU.\n\nGPU-less nodes \u2014 CPU workers and the control plane \u2014 still contribute their cpu, mem, and disk\nto the displayed inventory and the capacity calculation. "}, "OperatorPoolCapacity": {"properties": {"storage_class": {"type": "string", "title": "Storage Class"}, "capacity_bytes": {"type": "integer", "minimum": 0.0, "title": "Capacity Bytes"}}, "type": "object", "required": ["storage_class", "capacity_bytes"], "title": "OperatorPoolCapacity", "description": "What the CSI driver says a StorageClass's backing pool holds.\n\nRead from the CSIStorageCapacity objects the external-provisioner publishes. The control plane\ncannot ask a CSI driver anything \u2014 it never touches the workload API \u2014 and the only figure it\ncould see on its own is the storage node's root disk, which is not the pool."}, "OperatorSessionDisk": {"properties": {"name": {"type": "string", "title": "Name"}, "ephemeral_used_bytes": {"type": "integer", "title": "Ephemeral Used Bytes"}, "ephemeral_limit_bytes": {"type": "integer", "title": "Ephemeral Limit Bytes"}}, "type": "object", "required": ["name", "ephemeral_used_bytes", "ephemeral_limit_bytes"], "title": "OperatorSessionDisk", "description": "Ephemeral (scratch) disk usage of one session pod, read from kubelet /stats/summary.\n\n``name`` is the GShareSession CR name \u2014 the sanitized session id (``ses-01abc...``)."}, "OperatorStatusEvent": {"properties": {"phase": {"type": "string", "title": "Phase"}, "bound_gpu_uuid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Bound Gpu Uuid"}, "node_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Name"}, "yield_state": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Yield State"}, "pod_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pod Ref"}, "used_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Used Mem Mb"}, "message": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Message"}, "trace_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Trace Id"}, "restart_count": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Restart Count"}, "generation": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Generation"}, "container_state": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Container State"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "ts": {"type": "string", "format": "date-time", "title": "Ts"}}, "type": "object", "required": ["phase", "ts"], "title": "OperatorStatusEvent", "description": "Status callback payload. Drives consume/settle triggers."}, "OperatorVolumeObserved": {"properties": {"name": {"type": "string", "title": "Name"}, "volume_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Volume Id"}, "capacity_gb": {"type": "integer", "title": "Capacity Gb", "default": 0}, "used_bytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Used Bytes"}, "mounted": {"type": "boolean", "title": "Mounted", "default": false}, "storage_class": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Storage Class"}}, "type": "object", "required": ["name"], "title": "OperatorVolumeObserved", "description": "One PVC the operator sees in the session namespace (label gshare.io/volume)."}, "OperatorVolumeSync": {"properties": {"volumes": {"items": {"$ref": "#/components/schemas/OperatorVolumeObserved"}, "type": "array", "title": "Volumes"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "sessions": {"items": {"$ref": "#/components/schemas/OperatorSessionDisk"}, "type": "array", "title": "Sessions", "default": []}, "pools": {"items": {"$ref": "#/components/schemas/OperatorPoolCapacity"}, "type": "array", "title": "Pools", "default": []}}, "type": "object", "required": ["volumes"], "title": "OperatorVolumeSync", "description": "POST /internal/volumes/sync \u2014 the operator's periodic view of every session-volume PVC."}, "OrgAdminCreate": {"properties": {"user_id": {"type": "string", "title": "User Id"}}, "type": "object", "required": ["user_id"], "title": "OrgAdminCreate"}, "OrgCreate": {"properties": {"name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "create_node_pool": {"type": "boolean", "title": "Create Node Pool", "default": false}}, "type": "object", "required": ["name"], "title": "OrgCreate"}, "OrgUpdate": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80}, {"type": "null"}], "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}}, "type": "object", "title": "OrgUpdate"}, "PageMeta": {"properties": {"page": {"type": "integer", "title": "Page"}, "size": {"type": "integer", "title": "Size"}, "total": {"type": "integer", "title": "Total"}, "total_pages": {"type": "integer", "title": "Total Pages"}}, "type": "object", "required": ["page", "size", "total", "total_pages"], "title": "PageMeta", "description": "Standard pagination envelope (page/size/total/total_pages)."}, "PageMetaNoPages": {"properties": {"page": {"type": "integer", "title": "Page"}, "size": {"type": "integer", "title": "Size"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["page", "size", "total"], "title": "PageMetaNoPages", "description": "Pagination envelope without ``total_pages`` (queue list)."}, "PermissionBody": {"properties": {"user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "User Id"}, "email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Email"}, "role": {"type": "string", "pattern": "^(owner|rw|ro)$", "title": "Role"}}, "type": "object", "required": ["role"], "title": "PermissionBody"}, "PlacementOut": {"properties": {"gpu_packing": {"type": "string", "title": "Gpu Packing"}}, "type": "object", "required": ["gpu_packing"], "title": "PlacementOut"}, "PlacementUpdate": {"properties": {"gpu_packing": {"type": "string", "pattern": "^(binpack|spread)$", "title": "Gpu Packing"}}, "type": "object", "required": ["gpu_packing"], "title": "PlacementUpdate"}, "PolicyCreate": {"properties": {"scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "max_concurrent": {"type": "integer", "title": "Max Concurrent"}, "max_queued": {"type": "integer", "title": "Max Queued"}, "max_runtime_min": {"type": "integer", "title": "Max Runtime Min"}, "idle_timeout_sec": {"type": "integer", "title": "Idle Timeout Sec"}, "cpu_session_max_concurrent": {"type": "integer", "title": "Cpu Session Max Concurrent", "default": 1}, "cpu_session_max_runtime_min": {"type": "integer", "title": "Cpu Session Max Runtime Min", "default": 240}, "cpu_session_idle_timeout_sec": {"type": "integer", "title": "Cpu Session Idle Timeout Sec", "default": 1800}, "limits": {"additionalProperties": true, "type": "object", "title": "Limits", "default": {}}}, "type": "object", "required": ["scope", "scope_id", "max_concurrent", "max_queued", "max_runtime_min", "idle_timeout_sec"], "title": "PolicyCreate"}, "PolicyUpdate": {"properties": {"max_concurrent": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Max Concurrent"}, "max_queued": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Max Queued"}, "max_runtime_min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Max Runtime Min"}, "idle_timeout_sec": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Idle Timeout Sec"}, "cpu_session_max_concurrent": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu Session Max Concurrent"}, "cpu_session_max_runtime_min": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu Session Max Runtime Min"}, "cpu_session_idle_timeout_sec": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu Session Idle Timeout Sec"}, "limits": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Limits"}}, "type": "object", "title": "PolicyUpdate"}, "PoolGrantCreate": {"properties": {"scope": {"type": "string", "pattern": "^(org|group)$", "title": "Scope"}, "scope_id": {"type": "string", "minLength": 1, "title": "Scope Id"}}, "type": "object", "required": ["scope", "scope_id"], "title": "PoolGrantCreate"}, "PoolGrantRead": {"properties": {"id": {"type": "string", "title": "Id"}, "scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "created_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Created At"}}, "type": "object", "required": ["id", "scope", "scope_id"], "title": "PoolGrantRead"}, "PoolList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/PoolRead"}, "type": "array", "title": "Data"}, "total": {"type": "integer", "title": "Total"}}, "type": "object", "required": ["data", "total"], "title": "PoolList"}, "PoolNodeRow": {"properties": {"id": {"type": "string", "title": "Id"}, "hostname": {"type": "string", "title": "Hostname"}, "status": {"type": "string", "title": "Status"}, "device_count": {"type": "integer", "title": "Device Count"}}, "type": "object", "required": ["id", "hostname", "status", "device_count"], "title": "PoolNodeRow"}, "PoolPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80, "minLength": 1}, {"type": "null"}], "title": "Name"}, "storage_class": {"anyOf": [{"type": "string", "maxLength": 200, "minLength": 1}, {"type": "null"}], "title": "Storage Class"}, "node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}, "share_scope": {"anyOf": [{"type": "string", "pattern": "^(all|selected)$"}, {"type": "null"}], "title": "Share Scope"}, "shared_with": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Shared With"}, "manual_capacity_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Manual Capacity Gb"}}, "type": "object", "title": "PoolPatch"}, "PoolRead": {"properties": {"id": {"type": "string", "title": "Id"}, "cluster_id": {"type": "string", "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "name": {"type": "string", "title": "Name"}, "description": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Description"}, "kind": {"type": "string", "title": "Kind"}, "node_count": {"type": "integer", "title": "Node Count"}, "nodes": {"items": {"$ref": "#/components/schemas/PoolNodeRow"}, "type": "array", "title": "Nodes"}, "grants": {"items": {"$ref": "#/components/schemas/PoolGrantRead"}, "type": "array", "title": "Grants"}}, "type": "object", "required": ["id", "cluster_id", "name", "kind", "node_count", "nodes", "grants"], "title": "PoolRead"}, "PoolTargetsBody": {"properties": {"mig_cards": {"type": "integer", "minimum": 0.0, "title": "Mig Cards"}}, "type": "object", "required": ["mig_cards"], "title": "PoolTargetsBody"}, "PoolUpdate": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 120, "minLength": 1}, {"type": "null"}], "title": "Name"}, "description": {"anyOf": [{"type": "string", "maxLength": 1000}, {"type": "null"}], "title": "Description"}, "kind": {"anyOf": [{"type": "string", "pattern": "^(shared|dedicated)$"}, {"type": "null"}], "title": "Kind"}}, "type": "object", "title": "PoolUpdate"}, "PresetCreate": {"properties": {"name": {"type": "string", "title": "Name"}, "kind": {"type": "string", "title": "Kind", "default": "gpu"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "gpu_frac": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Gpu Frac"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}}, "type": "object", "required": ["name"], "title": "PresetCreate"}, "PresetUpdate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "gpu_frac": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Gpu Frac"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}}, "type": "object", "title": "PresetUpdate"}, "PreviewCostRequest": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "offering_id": {"type": "string", "title": "Offering Id"}, "image_id": {"type": "string", "title": "Image Id"}, "resource_class": {"type": "string", "pattern": "^(gpu|cpu)$", "title": "Resource Class"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_mode": {"type": "string", "pattern": "^(single|multi)$", "title": "Cluster Mode", "default": "single"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "gpu_mem_mb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer", "maximum": 100.0, "minimum": 0.0}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Disk Gb"}, "mode": {"anyOf": [{"type": "string", "pattern": "^(fractional|exclusive)$"}, {"type": "null"}], "title": "Mode"}, "billing_wallet_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Billing Wallet Id"}, "preemptible": {"type": "boolean", "title": "Preemptible", "default": false}, "privileged": {"type": "boolean", "title": "Privileged", "default": false}, "priority": {"type": "integer", "minimum": 0.0, "title": "Priority", "default": 0}, "volume_mounts": {"items": {"$ref": "#/components/schemas/VolumeMountSpec"}, "type": "array", "title": "Volume Mounts", "default": []}}, "additionalProperties": false, "type": "object", "required": ["offering_id", "image_id", "resource_class"], "title": "PreviewCostRequest"}, "PreviewCostResponse": {"properties": {"estimated_credit_per_hour": {"type": "number", "title": "Estimated Credit Per Hour"}, "occupancy": {"type": "number", "title": "Occupancy"}, "hold_amount": {"type": "number", "title": "Hold Amount"}}, "type": "object", "required": ["estimated_credit_per_hour", "occupancy", "hold_amount"], "title": "PreviewCostResponse"}, "ProjectCreate": {"properties": {"org_id": {"type": "string", "title": "Org Id"}, "name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "create_project_wallet": {"type": "boolean", "title": "Create Project Wallet", "default": true}, "default_member_credit": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Default Member Credit"}, "create_node_pool": {"type": "boolean", "title": "Create Node Pool", "default": false}}, "type": "object", "required": ["org_id", "name"], "title": "ProjectCreate"}, "ProjectPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80}, {"type": "null"}], "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "default_member_credit": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Default Member Credit"}}, "type": "object", "title": "ProjectPatch"}, "QueueEntryView": {"properties": {"id": {"type": "string", "title": "Id"}, "session_id": {"type": "string", "title": "Session Id"}, "priority": {"type": "integer", "title": "Priority"}, "status": {"type": "string", "title": "Status"}, "position": {"type": "integer", "title": "Position"}, "score": {"type": "number", "title": "Score"}, "session_req": {"additionalProperties": true, "type": "object", "title": "Session Req"}, "enqueued_at": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Enqueued At"}, "eta_minutes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Eta Minutes"}, "session_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Session Name"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["id", "session_id", "priority", "status", "position", "score", "session_req"], "title": "QueueEntryView", "description": "One queue entry as projected by ``_entry_view`` (status is always ``queued``)."}, "QueueList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/QueueEntryView"}, "type": "array", "title": "Data"}, "pagination": {"$ref": "#/components/schemas/PageMetaNoPages"}}, "type": "object", "required": ["data", "pagination"], "title": "QueueList", "description": "GET /queue envelope (pagination without total_pages)."}, "QueueMineList": {"properties": {"data": {"items": {"$ref": "#/components/schemas/QueueEntryView"}, "type": "array", "title": "Data"}}, "type": "object", "required": ["data"], "title": "QueueMineList", "description": "GET /queue/mine envelope (data only, no pagination)."}, "QueuePriorityPatch": {"properties": {"priority": {"type": "integer", "minimum": 0.0, "title": "Priority"}}, "type": "object", "required": ["priority"], "title": "QueuePriorityPatch"}, "RefillScheduleBody": {"properties": {"day": {"type": "integer", "maximum": 28.0, "minimum": 1.0, "title": "Day"}, "hour": {"type": "integer", "maximum": 23.0, "minimum": 0.0, "title": "Hour"}}, "type": "object", "required": ["day", "hour"], "title": "RefillScheduleBody"}, "ResourceRequestCreate": {"properties": {"group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "storage_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Storage Gb"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "note": {"type": "string", "title": "Note"}}, "type": "object", "required": ["note"], "title": "ResourceRequestCreate"}, "ResourceUsage": {"properties": {"used": {"type": "integer", "title": "Used"}, "limit": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Limit"}}, "type": "object", "required": ["used"], "title": "ResourceUsage", "description": "One compute dimension: what the caller's active sessions hold vs the policy limit\n(None = no limit configured)."}, "SessionCreate": {"properties": {"name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "offering_id": {"type": "string", "title": "Offering Id"}, "image_id": {"type": "string", "title": "Image Id"}, "resource_class": {"type": "string", "pattern": "^(gpu|cpu)$", "title": "Resource Class"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_mode": {"type": "string", "pattern": "^(single|multi)$", "title": "Cluster Mode", "default": "single"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "gpu_mem_mb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer", "maximum": 100.0, "minimum": 0.0}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Disk Gb"}, "mode": {"anyOf": [{"type": "string", "pattern": "^(fractional|exclusive)$"}, {"type": "null"}], "title": "Mode"}, "billing_wallet_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Billing Wallet Id"}, "preemptible": {"type": "boolean", "title": "Preemptible", "default": false}, "privileged": {"type": "boolean", "title": "Privileged", "default": false}, "priority": {"type": "integer", "minimum": 0.0, "title": "Priority", "default": 0}, "volume_mounts": {"items": {"$ref": "#/components/schemas/VolumeMountSpec"}, "type": "array", "title": "Volume Mounts", "default": []}}, "additionalProperties": false, "type": "object", "required": ["offering_id", "image_id", "resource_class"], "title": "SessionCreate"}, "SessionMountRead": {"properties": {"volume_id": {"type": "string", "title": "Volume Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Type"}, "quota_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Quota Gb"}, "mount_path": {"type": "string", "title": "Mount Path"}, "mode": {"type": "string", "title": "Mode"}}, "type": "object", "required": ["volume_id", "mount_path", "mode"], "title": "SessionMountRead", "description": "One mounted volume, joined with its display facts for the detail screens."}, "SessionRead": {"properties": {"id": {"type": "string", "title": "Id"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "status": {"type": "string", "title": "Status"}, "status_reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status Reason"}, "occupancy": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Occupancy"}, "bound_gpu_uuid": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Bound Gpu Uuid"}, "node_hostname": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Hostname"}, "node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}, "cluster_id": {"type": "string", "title": "Cluster Id"}, "group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "group_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Name"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}, "org_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Name"}, "resource_class": {"type": "string", "title": "Resource Class"}, "mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}, "gpu_mem_mb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Mem Mb"}, "gpu_cores": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Gpu Cores"}, "cpu": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Mem Gb"}, "disk_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Gb"}, "gpu_model": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Model"}, "gpu_alias": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Gpu Alias"}, "image_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Name"}, "image_ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Image Ref"}, "disk_used_bytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Used Bytes"}, "disk_limit_bytes": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Disk Limit Bytes"}, "mounts": {"items": {"$ref": "#/components/schemas/SessionMountRead"}, "type": "array", "title": "Mounts", "default": []}, "owner_user_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner User Id"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "credit_per_hour_snapshot": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Credit Per Hour Snapshot"}, "started_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Started At"}, "terminated_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Terminated At"}, "usage_summary": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Usage Summary"}, "credit_consumed": {"anyOf": [{"type": "number"}, {"type": "null"}], "title": "Credit Consumed"}, "queued_reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Queued Reason"}, "privileged": {"type": "boolean", "title": "Privileged", "default": false}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "status_changed_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Status Changed At"}}, "type": "object", "required": ["id", "status", "cluster_id", "resource_class"], "title": "SessionRead"}, "SignupPolicyOut": {"properties": {"mode": {"type": "string", "title": "Mode"}, "allowed_domains": {"items": {"type": "string"}, "type": "array", "title": "Allowed Domains", "default": []}}, "type": "object", "required": ["mode"], "title": "SignupPolicyOut"}, "SignupPolicyUpdate": {"properties": {"mode": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Mode"}, "allowed_domains": {"anyOf": [{"items": {"type": "string"}, "type": "array"}, {"type": "null"}], "title": "Allowed Domains"}}, "type": "object", "title": "SignupPolicyUpdate"}, "SpendDayRead": {"properties": {"date": {"type": "string", "title": "Date"}, "amount": {"type": "number", "title": "Amount"}}, "type": "object", "required": ["date", "amount"], "title": "SpendDayRead", "description": "One day of spend (consume + storage), for the wallet's usage chart."}, "TopupRejectBody": {"properties": {"reason": {"type": "string", "minLength": 1, "title": "Reason"}}, "type": "object", "required": ["reason"], "title": "TopupRejectBody"}, "TopupRequestBody": {"properties": {"amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}, "note": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Note"}, "wallet_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Id"}}, "type": "object", "required": ["amount"], "title": "TopupRequestBody"}, "TopupRequestListResponse": {"properties": {"data": {"items": {"$ref": "#/components/schemas/TopupRequestRead"}, "type": "array", "title": "Data"}}, "type": "object", "required": ["data"], "title": "TopupRequestListResponse"}, "TopupRequestRead": {"properties": {"id": {"type": "string", "title": "Id"}, "wallet_id": {"type": "string", "title": "Wallet Id"}, "amount": {"type": "string", "title": "Amount"}, "status": {"type": "string", "title": "Status"}, "requester_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Requester Id"}, "requester_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Requester Name"}, "note": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Note"}, "wallet_owner_type": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Owner Type"}, "wallet_owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Wallet Owner Name"}, "decided_reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Decided Reason"}, "decided_by": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Decided By"}, "created_at": {"type": "string", "title": "Created At"}}, "type": "object", "required": ["id", "wallet_id", "amount", "status", "created_at"], "title": "TopupRequestRead"}, "TransactionRead": {"properties": {"id": {"type": "string", "title": "Id"}, "type": {"type": "string", "title": "Type"}, "amount": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Amount"}, "balance_after": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Balance After"}, "ref": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Ref"}, "ref_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Ref Name"}, "created_at": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Created At"}, "entry_count": {"type": "integer", "title": "Entry Count", "default": 1}, "period_start": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Period Start"}, "period_end": {"anyOf": [{"type": "string", "format": "date-time"}, {"type": "null"}], "title": "Period End"}, "settled": {"type": "boolean", "title": "Settled", "default": false}, "live": {"type": "boolean", "title": "Live", "default": false}}, "type": "object", "required": ["id", "type", "amount", "balance_after"], "title": "TransactionRead"}, "TransferBody": {"properties": {"to_wallet_id": {"type": "string", "title": "To Wallet Id"}, "amount": {"anyOf": [{"type": "number", "maximum": 1000000000000.0, "exclusiveMinimum": 0.0}, {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$"}], "title": "Amount"}}, "type": "object", "required": ["to_wallet_id", "amount"], "title": "TransferBody"}, "UserApproveBody": {"properties": {"group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}, "initial_role": {"type": "string", "title": "Initial Role", "default": "member"}}, "type": "object", "title": "UserApproveBody", "description": "Department is optional: an administrator may let someone in and sort out the department\nlater, but doing both at once is the normal path."}, "UserCreate": {"properties": {"email": {"type": "string", "maxLength": 254, "minLength": 3, "title": "Email"}, "name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "group_id": {"type": "string", "title": "Group Id"}, "status": {"type": "string", "title": "Status", "default": "active"}, "initial_role": {"type": "string", "title": "Initial Role", "default": "member"}, "password": {"type": "string", "maxLength": 128, "minLength": 8, "title": "Password"}}, "type": "object", "required": ["email", "name", "group_id", "password"], "title": "UserCreate"}, "UserDepartmentSet": {"properties": {"group_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Group Id"}}, "type": "object", "title": "UserDepartmentSet"}, "UserPatch": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80}, {"type": "null"}], "title": "Name"}, "status": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Status"}, "email": {"anyOf": [{"type": "string", "maxLength": 254, "minLength": 3}, {"type": "null"}], "title": "Email"}, "password": {"anyOf": [{"type": "string", "maxLength": 128, "minLength": 8}, {"type": "null"}], "title": "Password"}, "force_password_reset": {"type": "boolean", "title": "Force Password Reset", "default": false}}, "additionalProperties": false, "type": "object", "title": "UserPatch"}, "ValidationError": {"properties": {"loc": {"items": {"anyOf": [{"type": "string"}, {"type": "integer"}]}, "type": "array", "title": "Location"}, "msg": {"type": "string", "title": "Message"}, "type": {"type": "string", "title": "Error Type"}, "input": {"title": "Input"}, "ctx": {"type": "object", "title": "Context"}}, "type": "object", "required": ["loc", "msg", "type"], "title": "ValidationError"}, "VolumeCreate": {"properties": {"scope": {"type": "string", "pattern": "^(user|group|global)$", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "type": {"type": "string", "pattern": "^(home|group|dataset|scratch)$", "title": "Type"}, "name": {"type": "string", "maxLength": 80, "minLength": 1, "title": "Name"}, "access_mode": {"type": "string", "pattern": "^(RWO|RWX|ROX)$", "title": "Access Mode"}, "quota_gb": {"type": "integer", "minimum": 0.0, "title": "Quota Gb"}}, "type": "object", "required": ["scope", "scope_id", "type", "name", "access_mode", "quota_gb"], "title": "VolumeCreate"}, "VolumeMountSpec": {"properties": {"volume_id": {"type": "string", "title": "Volume Id"}, "mount_path": {"type": "string", "title": "Mount Path"}, "mode": {"type": "string", "pattern": "^(ro|rw)$", "title": "Mode", "default": "rw"}}, "additionalProperties": false, "type": "object", "required": ["volume_id", "mount_path"], "title": "VolumeMountSpec"}, "VolumePatch": {"properties": {"quota_gb": {"anyOf": [{"type": "integer", "minimum": 1.0}, {"type": "null"}], "title": "Quota Gb"}, "access_mode": {"anyOf": [{"type": "string", "pattern": "^(RWO|RWX|ROX)$"}, {"type": "null"}], "title": "Access Mode"}, "mount_locked": {"anyOf": [{"type": "boolean"}, {"type": "null"}], "title": "Mount Locked"}}, "additionalProperties": false, "type": "object", "title": "VolumePatch", "description": "Owner-side edits. The quota only grows (bounded above by the scope's storage policy on the\nserver); `mount_locked` blocks new mounts so the volume can be drained for deletion."}, "VolumeRead": {"properties": {"id": {"type": "string", "title": "Id"}, "scope": {"type": "string", "title": "Scope"}, "scope_id": {"type": "string", "title": "Scope Id"}, "type": {"type": "string", "title": "Type"}, "name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Name"}, "access_mode": {"type": "string", "title": "Access Mode"}, "quota_gb": {"type": "integer", "title": "Quota Gb"}, "used_gb": {"type": "integer", "title": "Used Gb"}, "mount_locked": {"type": "boolean", "title": "Mount Locked", "default": false}, "role": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Role"}, "owner_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Id"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "shared_count": {"type": "integer", "title": "Shared Count", "default": 0}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}, "cluster_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Name"}, "storage_class": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Storage Class"}, "pool_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Id"}, "pool_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Pool Name"}, "active_mounts": {"anyOf": [{"items": {"additionalProperties": true, "type": "object"}, "type": "array"}, {"type": "null"}], "title": "Active Mounts"}}, "type": "object", "required": ["id", "scope", "scope_id", "type", "access_mode", "quota_gb", "used_gb"], "title": "VolumeRead"}, "VolumeSyncDirective": {"properties": {"name": {"type": "string", "title": "Name"}, "volume_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Volume Id"}, "quota_gb": {"anyOf": [{"type": "integer"}, {"type": "null"}], "title": "Quota Gb"}, "reclaim": {"type": "boolean", "title": "Reclaim", "default": false}}, "type": "object", "required": ["name"], "title": "VolumeSyncDirective", "description": "What the control plane wants for one observed PVC."}, "VolumeSyncResponse": {"properties": {"volumes": {"items": {"$ref": "#/components/schemas/VolumeSyncDirective"}, "type": "array", "title": "Volumes"}, "orphans": {"type": "integer", "title": "Orphans", "default": 0}}, "type": "object", "required": ["volumes"], "title": "VolumeSyncResponse"}, "WalletRead": {"properties": {"id": {"type": "string", "title": "Id"}, "owner_type": {"type": "string", "title": "Owner Type"}, "owner_id": {"type": "string", "title": "Owner Id"}, "balance": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Balance"}, "reserved": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Reserved"}, "monthly_grant": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Monthly Grant", "default": "0"}, "owner_name": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Owner Name"}, "available": {"type": "string", "pattern": "^(?!^[-+.]*$)[+-]?0*\\d*\\.?\\d*$", "title": "Available", "readOnly": true}}, "type": "object", "required": ["id", "owner_type", "owner_id", "balance", "reserved", "available"], "title": "WalletRead"}, "WebhookCreate": {"properties": {"url": {"type": "string", "title": "Url"}, "events": {"items": {"type": "string"}, "type": "array", "title": "Events"}, "secret": {"type": "string", "title": "Secret"}, "scope": {"anyOf": [{"additionalProperties": true, "type": "object"}, {"type": "null"}], "title": "Scope"}, "org_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Org Id"}}, "type": "object", "required": ["url", "events", "secret"], "title": "WebhookCreate"}, "_CordonBody": {"properties": {"cordon": {"type": "boolean", "title": "Cordon", "default": true}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "_CordonBody"}, "_DeviceAliasBody": {"properties": {"alias": {"anyOf": [{"type": "string", "maxLength": 32}, {"type": "null"}], "title": "Alias"}}, "type": "object", "title": "_DeviceAliasBody"}, "_DeviceHealthBody": {"properties": {"status": {"type": "string", "enum": ["ready", "unhealthy"], "title": "Status"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "required": ["status"], "title": "_DeviceHealthBody"}, "_DrainBody": {"properties": {"mode": {"type": "string", "pattern": "^(reschedule|force_terminate)$", "title": "Mode", "default": "reschedule"}, "reason": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Reason"}}, "type": "object", "title": "_DrainBody"}, "_LoginRequest": {"properties": {"email": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Email"}, "password": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Password"}}, "type": "object", "title": "_LoginRequest"}, "_NodeRegister": {"properties": {"hostname": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Hostname"}, "region": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Region"}, "cpu": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Cpu"}, "mem_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Mem Gb"}, "cluster_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Cluster Id"}}, "type": "object", "required": ["hostname"], "title": "_NodeRegister"}, "_RRReject": {"properties": {"reason": {"type": "string", "title": "Reason"}}, "type": "object", "required": ["reason"], "title": "_RRReject"}, "_SignupRequest": {"properties": {"email": {"type": "string", "maxLength": 254, "minLength": 3, "title": "Email"}, "name": {"type": "string", "maxLength": 100, "minLength": 1, "title": "Name"}, "password": {"type": "string", "maxLength": 128, "minLength": 8, "title": "Password"}}, "type": "object", "required": ["email", "name", "password"], "title": "_SignupRequest"}, "app__api__schemas__node_pool__PoolCreate": {"properties": {"cluster_id": {"type": "string", "title": "Cluster Id"}, "name": {"type": "string", "maxLength": 120, "minLength": 1, "title": "Name"}, "description": {"anyOf": [{"type": "string", "maxLength": 1000}, {"type": "null"}], "title": "Description"}, "kind": {"type": "string", "pattern": "^(shared|dedicated)$", "title": "Kind", "default": "dedicated"}}, "type": "object", "required": ["cluster_id", "name"], "title": "PoolCreate"}, "app__api__storage_pools_router__PoolCreate": {"properties": {"name": {"anyOf": [{"type": "string", "maxLength": 80, "minLength": 1}, {"type": "null"}], "title": "Name"}, "cluster_id": {"type": "string", "title": "Cluster Id"}, "storage_class": {"type": "string", "maxLength": 200, "minLength": 1, "title": "Storage Class"}, "node_id": {"anyOf": [{"type": "string"}, {"type": "null"}], "title": "Node Id"}, "share_scope": {"type": "string", "pattern": "^(all|selected)$", "title": "Share Scope", "default": "all"}, "shared_with": {"items": {"type": "string"}, "type": "array", "title": "Shared With", "default": []}, "manual_capacity_gb": {"anyOf": [{"type": "integer", "minimum": 0.0}, {"type": "null"}], "title": "Manual Capacity Gb"}}, "type": "object", "required": ["cluster_id", "storage_class"], "title": "PoolCreate"}}}} diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 25bd766..0705cc5 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -11,43 +11,44 @@ "@phosphor-icons/react": "^2.1.10", "@tanstack/react-query": "^5.51.0", "@types/papaparse": "^5.5.2", - "i18next": "^23.16.8", - "i18next-browser-languagedetector": "^7.2.2", + "i18next": "^26.4.2", + "i18next-browser-languagedetector": "^8.2.1", "openapi-fetch": "^0.10.5", "papaparse": "^5.6.0", "pretendard": "^1.3.9", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-i18next": "^14.1.3", - "react-router-dom": "^6.30.6", + "react-i18next": "^17.0.13", + "react-router-dom": "^7.18.3", "uplot": "^1.6.32", "zustand": "^4.5.4" }, "devDependencies": { + "@eslint/js": "^10.0.1", + "@tailwindcss/postcss": "^4.3.3", "@testing-library/react": "^16.0.0", - "@types/node": "^20.14.0", + "@types/node": "^22.0.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "@vitejs/plugin-react": "^4.3.1", - "autoprefixer": "^10.4.19", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.9", - "jsdom": "^24.1.1", + "@vitejs/plugin-react": "^6.1.1", + "eslint": "^10.10.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.6", + "globals": "^17.0.0", + "jsdom": "^30.0.1", "openapi-typescript": "^7.3.0", "postcss": "^8.4.40", - "tailwindcss": "^3.4.7", + "tailwindcss": "^4.3.3", "typescript": "^5.5.4", - "vite": "^5.3.5", - "vitest": "^2.0.5" + "typescript-eslint": "^8.70.0", + "vite": "^8.3.0", + "vitest": "^5.0.0" } }, "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.3.0.tgz", + "integrity": "sha512-U4+70Pc5ZS9osnCBCE5Jha/ciHM+Yp+CNMNC/7HvYbNRk1Ldd+f7qO65W5qfhu/TCv+/ozljlXXe9Nj8419DMA==", "dev": true, "license": "MIT", "engines": { @@ -58,25 +59,57 @@ } }, "node_modules/@asamuzakjp/css-color": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-3.2.0.tgz", - "integrity": "sha512-K1A6z8tS3XsmCMM86xoWdn7Fkdn9m6RSVtocUrJYIwZnFVkng/PvkEoWtOWmP+Scc6saYWHWZYbndEEXxl24jw==", + "version": "6.0.7", + "resolved": "https://registry.npmjs.org/@asamuzakjp/css-color/-/css-color-6.0.7.tgz", + "integrity": "sha512-vC/bk1Lz7Tn/EfU9/apOTBk80/8dyGyWMowPoV1tJ52muDGsDqt2HPT2klrFUiY60MQmQv9q8yIht15JnBgDGw==", "dev": true, "license": "MIT", "dependencies": { - "@csstools/css-calc": "^2.1.3", - "@csstools/css-color-parser": "^3.0.9", - "@csstools/css-parser-algorithms": "^3.0.4", - "@csstools/css-tokenizer": "^3.0.3", - "lru-cache": "^10.4.3" + "@csstools/css-calc": "^3.3.0", + "@csstools/css-color-parser": "^4.1.10", + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0", + "lru-cache": "^11.5.2" + }, + "engines": { + "node": "^22.13.0 || >=24.0.0" } }, "node_modules/@asamuzakjp/css-color/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", "dev": true, - "license": "ISC" + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@asamuzakjp/dom-selector": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/@asamuzakjp/dom-selector/-/dom-selector-8.3.2.tgz", + "integrity": "sha512-93Z1N+BQNXysodoicpOIyNh2drHfz/CTf9nnT0FEx72GJcIiwgydD7tGAr78j41LsYn3hlRn+LdGPuBLn1Bl8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "bidi-js": "^1.0.3", + "css-tree": "^3.2.1", + "is-potential-custom-element-name": "^1.0.1", + "lru-cache": "^11.5.2" + }, + "engines": { + "node": "^22.13.0 || >=24.0.0" + } + }, + "node_modules/@asamuzakjp/dom-selector/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } }, "node_modules/@babel/code-frame": { "version": "7.29.7", @@ -134,25 +167,15 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.7.tgz", - "integrity": "sha512-DkXD5OJQaAQIdZ1bt3UZdEnHAn9Imd3IVBdX03UFe+ony9Ojw5pzr9YVKGDY1jt+Gcn/FnGkNf8r+Vj5NOJWtQ==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.29.7", - "@babel/types": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -178,16 +201,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-globals": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", @@ -230,16 +243,6 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", - "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-string-parser": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", @@ -285,13 +288,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.7.tgz", - "integrity": "sha512-hnORnjP/1P/zFEndoeX+n+t1RwWRJiJpM/jO7FW32Kn9r5+sJB2JWOdYo4L6k78j15eCwY3Gm/7364B1EMwtNg==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.29.7" + "@babel/types": "^7.29.8" }, "bin": { "parser": "bin/babel-parser.js" @@ -300,38 +303,6 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", - "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", - "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.29.7" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, "node_modules/@babel/runtime": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", @@ -357,18 +328,18 @@ } }, "node_modules/@babel/traverse": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.7.tgz", - "integrity": "sha512-EhlfNQtZ+NK22w5BM61ciuiq1m58ed33Wr1Xan//ZRTy6hgjnwyCffRYwzsGXdASJSUJ1guZILsErh1eQcl+zw==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.29.7", - "@babel/generator": "^7.29.7", + "@babel/generator": "^7.29.8", "@babel/helper-globals": "^7.29.7", - "@babel/parser": "^7.29.7", + "@babel/parser": "^7.29.8", "@babel/template": "^7.29.7", - "@babel/types": "^7.29.7", + "@babel/types": "^7.29.8", "debug": "^4.3.1" }, "engines": { @@ -376,9 +347,9 @@ } }, "node_modules/@babel/types": { - "version": "7.29.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.7.tgz", - "integrity": "sha512-4zBIxpPzowiZpusoFkyGVwakdRJUyuH5PxQ/PrqghfdFWWasvnCdPfQXHrenDai+gyLARulZjZowCOj6fjT4pA==", + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", "dev": true, "license": "MIT", "dependencies": { @@ -389,10 +360,47 @@ "node": ">=6.9.0" } }, + "node_modules/@bramus/specificity": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@bramus/specificity/-/specificity-2.4.2.tgz", + "integrity": "sha512-ctxtJ/eA+t+6q2++vj5j7FYX3nRu311q1wfYH3xjlLOsczhlhxAg2FWNUXhpGvAw3BWo1xBcvOV6/YLc2r5FJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "css-tree": "^3.0.0" + }, + "bin": { + "specificity": "bin/cli.js" + } + }, + "node_modules/@cacheable/memory": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cacheable/memory/-/memory-2.2.0.tgz", + "integrity": "sha512-CTLKqLItRCEixEAewD3/j9DB3/o96gpTPD4eJ1v+DGOlxZRZncRQkGYqqnAGCscYd6RNeXfGeiuCphsPtqyIfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cacheable/utils": "^2.5.0", + "@keyv/bigmap": "^1.3.1", + "hookified": "^1.15.1", + "keyv": "^5.6.0" + } + }, + "node_modules/@cacheable/utils": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@cacheable/utils/-/utils-2.5.0.tgz", + "integrity": "sha512-buipgOVDkkPXNR5+xBpDw7Zk2n1EvU7qBJCNUcL7rhQ//kfpOXPAvQ511Os0vpLYJ1pZnvudNytkQt2hst3wqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hashery": "^1.5.1", + "keyv": "^5.6.0" + } + }, "node_modules/@csstools/color-helpers": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-5.1.0.tgz", - "integrity": "sha512-S11EXWJyy0Mz5SYvRmY8nJYTFFd1LCNV+7cXyAgQtOOuzb4EsgfqDufL+9esx72/eLhsRdGZwaldu/h+E4t4BA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@csstools/color-helpers/-/color-helpers-6.1.1.tgz", + "integrity": "sha512-gLNsunvwf3mCi5u5o46/Z/JcJMnhbHSaZ69rkgPzNM3J4s8hWwpPUQB6/tt0EDFyCiWzxANlx+2LJwpYj4zS1w==", "dev": true, "funding": [ { @@ -406,13 +414,13 @@ ], "license": "MIT-0", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, "node_modules/@csstools/css-calc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-2.1.4.tgz", - "integrity": "sha512-3N8oaj+0juUw/1H3YwmDDJXCgTB1gKU6Hc/bB502u9zR0q2vd786XJH9QfrKIEgFlZmhZiq6epXl4rHqhzsIgQ==", + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-3.3.0.tgz", + "integrity": "sha512-c5ihYsPkdG6JCkU2zTMm4+k6r7RXuGxtWYhu5DHMIiF1FHzrfmHL5so11AoFpUv/tu61xfcmT4AmKoFfMPoqdQ==", "dev": true, "funding": [ { @@ -426,17 +434,17 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-color-parser": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-3.1.0.tgz", - "integrity": "sha512-nbtKwh3a6xNVIp/VRuXV64yTKnb1IjTAEEh3irzS+HkKjAOYLTGNb9pmVNntZ8iVBHcWDA2Dof0QtPgFI1BaTA==", + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@csstools/css-color-parser/-/css-color-parser-4.2.2.tgz", + "integrity": "sha512-3QKjR/vxyjcSXBLgb6lP0S3MGdvwbmqSsvLPbYdVORqPDc8FX1HAJ0Spk38bxaRXgvENTA47tlhhbb5Z2e8hEg==", "dev": true, "funding": [ { @@ -450,21 +458,21 @@ ], "license": "MIT", "dependencies": { - "@csstools/color-helpers": "^5.1.0", - "@csstools/css-calc": "^2.1.4" + "@csstools/color-helpers": "^6.1.1", + "@csstools/css-calc": "^3.3.0" }, "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-parser-algorithms": "^3.0.5", - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-parser-algorithms": "^4.0.0", + "@csstools/css-tokenizer": "^4.0.0" } }, "node_modules/@csstools/css-parser-algorithms": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-3.0.5.tgz", - "integrity": "sha512-DaDeUkXZKjdGhgYaHNJTV9pV7Y9B3b644jCLs9Upc3VeNGg6LWARAT6O+Q+/COo+2gg/bM5rhpMAtf70WqfBdQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-4.0.0.tgz", + "integrity": "sha512-+B87qS7fIG3L5h3qwJ/IFbjoVoOe/bpOdh9hAjXbvx0o8ImEmUsGXN0inFOnk2ChCFgqkkGFQ+TpM5rbhkKe4w==", "dev": true, "funding": [ { @@ -478,16 +486,41 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" }, "peerDependencies": { - "@csstools/css-tokenizer": "^3.0.4" + "@csstools/css-tokenizer": "^4.0.0" + } + }, + "node_modules/@csstools/css-syntax-patches-for-csstree": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/@csstools/css-syntax-patches-for-csstree/-/css-syntax-patches-for-csstree-1.1.13.tgz", + "integrity": "sha512-i9ZylF5QNhmNfPA9l0vHAWK4kPrbIp6g9lKgaiIFsIBz2F/WNB7OLrzlNNcCOm+h42bkaSD2v1PG+IBPHhc3ZA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "peerDependencies": { + "css-tree": "^3.2.1" + }, + "peerDependenciesMeta": { + "css-tree": { + "optional": true + } } }, "node_modules/@csstools/css-tokenizer": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-3.0.4.tgz", - "integrity": "sha512-Vd/9EVDiu6PPJt9yAh6roZP6El1xHrdvIVGjyBsHR0RYwNHgL7FJPyIIW4fANJNG6FtyZfvlRPpFI4ZM/lubvw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-4.0.0.tgz", + "integrity": "sha512-QxULHAm7cNu72w97JUNCBFODFaXpbDg+dP8b/oWFAZ2MTRppA3U00Y2L1HqaS4J6yBqxwa/Y3nMBaxVKbB/NsA==", "dev": true, "funding": [ { @@ -501,525 +534,191 @@ ], "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20.19.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], "engines": { - "node": ">=12" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/config-array": { + "version": "0.23.5", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.23.5.tgz", + "integrity": "sha512-Y3kKLvC1dvTOT+oGlqNQ1XLqK6D1HU2YXPc52NmAlJZbMMWDzGYXMiPRJ8TYD39muD/OTjlZmNJ4ib7dvSrMBA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^3.0.5", + "debug": "^4.3.1", + "minimatch": "^10.2.4" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/config-helpers": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.7.0.tgz", + "integrity": "sha512-DObd/KKUsU+FaFv4PLxSRenpXfQWmPXXP3pPZ6/K1PCrMu2vQpMDMuQe/BqYeoLcz8ro0bVDF1RxOJgfVEdhUw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/core": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-1.2.1.tgz", + "integrity": "sha512-MwcE1P+AZ4C6DWlpin/OmOA54mmIZ/+xZuJiQd4SyB29oAJjN30UW9wkKNptW2ctp4cEsvhlLY/CsQ1uoHDloQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], + "node_modules/@eslint/js": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-10.0.1.tgz", + "integrity": "sha512-zeR9k5pd4gxjZ0abRoIaxdc7I3nDktoXZk2qOv9gCNWx3mVwEn32VRhyLaRsDiJjTs0xq/T8mfPtyuXu7GWBcA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "eslint": "^10.0.0" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], + "node_modules/@eslint/object-schema": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-3.0.5.tgz", + "integrity": "sha512-vqTaUEgxzm+YDSdElad6PiRoX4t8VGDjCtt05zn4nU810UIx/uNEV7/lZJ6KwFThKZOzOxzXy48da+No7HZaMw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "license": "Apache-2.0", "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], + "node_modules/@eslint/plugin-kit": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.7.3.tgz", + "integrity": "sha512-IkO+/KEUvwbVpiURZg+P7zF74z5Jxe0UgJxVni+RtoHQ6IZieXaO02kmadomap/q+l6bc/jdPGGqTjhuZnuz1Q==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^1.2.1", + "levn": "^0.4.1" + }, "engines": { - "node": ">=12" + "node": "^20.19.0 || ^22.13.0 || >=24" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], + "node_modules/@exodus/bytes": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@exodus/bytes/-/bytes-1.15.1.tgz", + "integrity": "sha512-S6mL0yNB/Abt9Ei4tq8gDhcczc4S3+vQ4ra7vxnAf+YHC02srtqxKKZghx2Dq6p0e66THKwR6r8N6P95wEty7Q==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", - "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" }, "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", - "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" + "@noble/hashes": "^1.8.0 || ^2.0.0" }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "peerDependenciesMeta": { + "@noble/hashes": { + "optional": true + } } }, - "node_modules/@eslint/eslintrc/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "node_modules/@humanfs/core": { + "version": "0.19.2", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz", + "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==", "dev": true, - "license": "ISC", + "license": "Apache-2.0", "dependencies": { - "brace-expansion": "^1.1.7" + "@humanfs/types": "^0.15.0" }, "engines": { - "node": "*" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", + "node_modules/@humanfs/node": { + "version": "0.16.8", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz", + "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==", "dev": true, "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@humanfs/core": "^0.19.2", + "@humanfs/types": "^0.15.0", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, - "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "node_modules/@humanfs/types": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz", + "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==", "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, + "license": "Apache-2.0", "engines": { - "node": "*" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -1036,13 +735,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", @@ -1077,9 +782,9 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz", + "integrity": "sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==", "dev": true, "license": "MIT" }, @@ -1094,48 +799,45 @@ "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "node_modules/@keyv/bigmap": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@keyv/bigmap/-/bigmap-1.3.1.tgz", + "integrity": "sha512-WbzE9sdmQtKy8vrNPa9BRnwZh5UF4s1KTmSK0KUVLo3eff5BlQNNWDnFOouNpKfPKDnms9xynJjsMYjMaT/aFQ==", "dev": true, "license": "MIT", "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" + "hashery": "^1.4.0", + "hookified": "^1.15.0" }, "engines": { - "node": ">= 8" + "node": ">= 18" + }, + "peerDependencies": { + "keyv": "^5.6.0" } }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "node_modules/@keyv/serialize": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@keyv/serialize/-/serialize-1.1.1.tgz", + "integrity": "sha512-dXn3FZhPv0US+7dtJsIi2R+c7qWYiReoEh5zUntWCf4oSpMNib8FDhSoed6m3QyZdx5hK7iLFkYk3rNxwt8vTA==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } + "license": "MIT" }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "node_modules/@oxc-project/types": { + "version": "0.149.0", + "resolved": "https://registry.npmjs.org/@oxc-project/types/-/types-0.149.0.tgz", + "integrity": "sha512-Efcc+iF0j3Bf67YjEqIqWXbX5XddXoK/Mw4K1/JuXwRCZ8N16VR7iT23nlCc9XrveFVh/E5Rqs2StT0V8v9LdA==", "dev": true, "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" + "funding": { + "url": "https://github.com/sponsors/oxc-project" } }, "node_modules/@phosphor-icons/react": { "version": "2.1.10", "resolved": "https://registry.npmjs.org/@phosphor-icons/react/-/react-2.1.10.tgz", "integrity": "sha512-vt8Tvq8GLjheAZZYa+YG/pW7HDbov8El/MANW8pOAz4eGxrwhnbfrQZq0Cp4q8zBEu8NIhHdnr+r8thnfRSNYA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -1197,6 +899,23 @@ "npm": ">=9.5.0" } }, + "node_modules/@redocly/openapi-core/node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@redocly/openapi-core/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, "node_modules/@redocly/openapi-core/node_modules/minimatch": { "version": "5.1.9", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", @@ -1210,26 +929,10 @@ "node": ">=10" } }, - "node_modules/@remix-run/router": { - "version": "1.23.4", - "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.4.tgz", - "integrity": "sha512-q7j5geK7xs3UJSdm9/iytUNclBnLmYx1EnSeCFXHPeutdqgIMeFeHtUZgS3EhlKxdBEAu8OwtJCwmLrEzpSs7Q==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.61.1.tgz", - "integrity": "sha512-JnBB8MdXj45cajvTuO5FmPlvFVJRQgvrz1uSEl3NwqFnReAPGwb8EanbGi4z2nRaqLzjJSv5/JmycoTKlRZxHA==", + "node_modules/@rolldown/binding-android-arm-eabi": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.8.tgz", + "integrity": "sha512-tN5aztYkKCte4i5SIrrz5yK/HMjEuCqCSCJa418jOV8tZ1cBY3YF2otxB1ktPxzsLA1BeTqwapK0bfjxNvHJVw==", "cpu": [ "arm" ], @@ -1238,12 +941,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.61.1.tgz", - "integrity": "sha512-Jx2g7iSjw4AOT0HDPHM9RV3GNjRXwybWtSFZiZAYUTjUwjVrYIwq3kBf+LnhqJlzXFAqTAh2F7IGI+O568exPw==", + "node_modules/@rolldown/binding-android-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.8.tgz", + "integrity": "sha512-dIYTWl9XprMUiQFoc55KUyk/oS8SKYH3zFl0LTR7RT0Xj4hgSVyuJcroH8JUu8RcpF8fTB6E0aOwCkZoYPcDSQ==", "cpu": [ "arm64" ], @@ -1252,12 +958,15 @@ "optional": true, "os": [ "android" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.61.1.tgz", - "integrity": "sha512-0F1L/Z3Eqv8mT2n3dCpeO8GcTvHvVqkP5/t6DMsn0KzhYVcg+s7Ncl5DS8qjKYEeio6Az0Gt6nyBORay5qIlCA==", + "node_modules/@rolldown/binding-darwin-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.8.tgz", + "integrity": "sha512-PCSDQGXD2IyTEFrcgPyBM8jJuGmrbCMuoIOXdbEGVemruKACXoLQJrb+A45Z0L5t1RQkdfJprAYPkikbh7dzdA==", "cpu": [ "arm64" ], @@ -1266,12 +975,15 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.61.1.tgz", - "integrity": "sha512-qLttcH871ujY4YcVfUSShhOw+CsoTatYz8gRbHO7Bb92QH059/P0y5do1KMs41fY0BpD2x4AJH/gID0zFiqVKQ==", + "node_modules/@rolldown/binding-darwin-x64": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.8.tgz", + "integrity": "sha512-Uk7lRsGhPFHVX/sAUC6D5H9Ol30dFHd6iquokll2th3LpdJ3F5CzQB+7DHn0Ri2mG+U7k2zXiPHDrwZenXhwSA==", "cpu": [ "x64" ], @@ -1280,208 +992,368 @@ "optional": true, "os": [ "darwin" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.61.1.tgz", - "integrity": "sha512-fUI4RapGE0Oh3mb8mgfvC1O2nU1RpDZUKnDQm3xB1Ipg7C2wTs5Kstz7G2uWK99a8S2yTMq8/P4uycwNa0nJyw==", + "node_modules/@rolldown/binding-freebsd-x64": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.8.tgz", + "integrity": "sha512-DjszaTEVogPqA5bYzsEeqDCQxbcp2fexQwKcRspYji2yzR68fCf+e4fx6kBSRDwX5/brZaHw/hWS9+A/+/w9sQ==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "freebsd" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.61.1.tgz", - "integrity": "sha512-H5YrdvJaDtI/U9/emrD4b++xkvp3y/JvOe4rizHbxvkyMfRS/CiRYdji+Pl8D0brEaNFWUh1drQxgAGIl6Xudw==", + "node_modules/@rolldown/binding-linux-arm-gnueabihf": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.8.tgz", + "integrity": "sha512-zmwa7FTmdzB6aaEEuuls18H6Ap5JmJPSoPTuXixeJZV6tG40SyLkApQtz1g8ptZtiEKqj9OM0oNLPh1AgvE31Q==", "cpu": [ - "x64" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "freebsd" - ] + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.61.1.tgz", - "integrity": "sha512-Q8CBCCQtDFrYtXoeUXSrnFXKOnyUhx6bz+SkL6A0E7V8kAiCJ5pamq1WtbfpVGhR5TSpXY6ak3avmDc5fHTyJA==", + "node_modules/@rolldown/binding-linux-arm64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.8.tgz", + "integrity": "sha512-KdYQDPHwJVnbFwdTGMgxsI9SqblBlz6STGM+w1We/d5B8OWWidYH0MwkU/uA1wM5fIpO2MkOVxXrNzzuZhw9ew==", "cpu": [ - "arm" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.61.1.tgz", - "integrity": "sha512-nwnhk1581l0FBVellGcVCAT0Oi06onEA3WB53sf01VO3I0UPBkMH9sXONYME2K0ovXcNayJfNtHfm6mpJElatQ==", + "node_modules/@rolldown/binding-linux-arm64-musl": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.8.tgz", + "integrity": "sha512-jFJTifHnNPY+yzOoNZQfSIysrVyXzEQPhPnOUjmD1bcQGHH6s7c8cViKWar8YplQImE5N9JRqMCLrM2CdxOrZA==", "cpu": [ - "arm" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.61.1.tgz", - "integrity": "sha512-x5Xr49hwt3hdW75UOZm3395YwwzPyauktslv29KpWL/T+vVAzoT3azLcTWv0eMciBNrx+DYjH4paehHoLpPvpg==", + "node_modules/@rolldown/binding-linux-ppc64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.8.tgz", + "integrity": "sha512-FhiOziBDWPBjbcmRzfLyIJnaP7AVMFXT7YCXPjXxj7wKU3vx24RjrCNN/zjvVa+N2vVoHJwCoUBvsrN/DG3zIA==", "cpu": [ - "arm64" + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-s390x-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.8.tgz", + "integrity": "sha512-WnHfADMzOV2Y55wlx1hzzQnar/wDt/VdvWSD99r18Mz9ylNieIGOkRx3UV21h7m/eJvjySYJkO26VvGNFkwsIQ==", + "cpu": [ + "s390x" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-gnu": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.8.tgz", + "integrity": "sha512-H9tRr5ibfXFVLxbPOseVewewFpl28zcEdjRDt2FTUZU7odxP0gEv1ki4/kGmcGOh78oRwZuuQllGLZ9zTJp84g==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-linux-x64-musl": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.8.tgz", + "integrity": "sha512-UefiqfM3D6IVNlZ8tSGs9+Ejjud2T+oxO0IHADU45Y+lyEjD2dVFyZHbkfX0LUb5Zugo/oIv1eCO/KVYhgYJYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-openharmony-arm64": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.8.tgz", + "integrity": "sha512-637Ke4kWSy6rp9cxQ9gMOXlxPgIw/c1beASV4M//3+9I4uwBVOOl74G+e3zyU3u19U7RkRl/HuewixZ/Z6+Rjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/binding-win32-arm64-msvc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.8.tgz", + "integrity": "sha512-xWBkPOF1Q9k/Gv1nQXnVdLxKu74jXppuOM4Z3mnypVUJJJwLsMl7hNJGRAUJoG8A5MgOI1ACKM+wBFxSJzKy4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.61.1.tgz", - "integrity": "sha512-unMS3H73DpaoPyyEVPjGKleM/s0mkmsauTENpw4INQY8y4+IuLNjkueQ5QCtC0D3N38Y38yhAU8OoZ20S2Tm6w==", + "node_modules/@rolldown/binding-win32-x64-msvc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.8.tgz", + "integrity": "sha512-uz2ZvfgXbxqNwijjjbxrnvALwpyODDcgc1T1N8N3rf/DXKQmaFwmB4LX4yyjggpwN2obdQLb2rgirX5ffCWYng==", "cpu": [ - "arm64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.61.1.tgz", - "integrity": "sha512-zNZzGRnAhwjFEYmvphJRV5XaQGjs62cCmeYYHUT//NbvEnHauw+I85nGG+SiVg5ld4GX8D1IbKIX+ozITQnhMQ==", - "cpu": [ - "loong64" + "win32" ], + "engines": { + "node": "^20.19.0 || >=22.12.0" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz", + "integrity": "sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tailwindcss/node": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.3.3.tgz", + "integrity": "sha512-/T8IKEsf9VTU6tLjgC7+sv2mOPtQxzE2jMw7u4Tt40Tx+QSZxpzh95/H6cMKoja9XuW7iMdLJYBB0o9G1CaAgg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] + "dependencies": { + "@jridgewell/remapping": "^2.3.5", + "enhanced-resolve": "^5.24.1", + "jiti": "^2.7.0", + "lightningcss": "1.32.0", + "magic-string": "^0.30.21", + "source-map-js": "^1.2.1", + "tailwindcss": "4.3.3" + } }, - "node_modules/@rollup/rollup-linux-loong64-musl": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.61.1.tgz", - "integrity": "sha512-LdpWGL8X209B2SIvWjqlc8VZgM6PKfontSerGepuldQmHYrAOtnMCXeJkxXGbC+PPZVOuu5czJo7fNV6aeW8rQ==", + "node_modules/@tailwindcss/oxide": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.3.3.tgz", + "integrity": "sha512-krXjAikiaFSPaK/FkAQT5UTx3VormQaiZ5hBFlJZ9UFQGB/rwg1MZIhHAG9smMQRTdyJxP6Qt5MwMtdyU5FWrA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20" + }, + "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" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.3.3.tgz", + "integrity": "sha512-Y85A2gmPSkl5Ve5qR86GL4HT509cFqQh1aes9p3sSkyTPwt0Pppf3GkwGe4JPACcRYjgJIEhQgM6dBClnr0NYw==", "cpu": [ - "loong64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "android" + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.61.1.tgz", - "integrity": "sha512-EC5kTtNaNGOmbMGqar8dvJy6y/hg99GAwjfBz++pxZhQATXGcRjd6c5en5wcbru0vkRmiMGsQKdMJOOf6sza4g==", + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.3.3.tgz", + "integrity": "sha512-BiaWatpBcERQFDlOjRDpIVXuFK5PJez5SA4JMg6VYZdBYU+qKfV/vqjcIs+IYmtitf1xYQZTwXvU/8y4lfZUGw==", "cpu": [ - "ppc64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "darwin" + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-linux-ppc64-musl": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.61.1.tgz", - "integrity": "sha512-8hiwp6D4acEcNK78I4rP0/XtS1sknWIAMJBPdR4l6zUtyTm5KiTDr5bXmWt4foY7nAN7AThDHgkLIEZOWKbzWw==", + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.3.3.tgz", + "integrity": "sha512-fAeUqfV5ndhxRwai8cXGzdLvul9utWOmeTkv69unv4ZXixjn61Z+p9lCWdwOwA3TYboG3BwdVuN/RDjhBRl0mw==", "cpu": [ - "ppc64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "darwin" + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.61.1.tgz", - "integrity": "sha512-10dh/h/BqA7DuMPWSxkR8uks18FRwnwOEqr5zOTEl+NOwP/OMzKX8OFR/Of9xxDA7D5qef1Nzar5WDD2kCCr1g==", + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.3.3.tgz", + "integrity": "sha512-iyf5bV6+wnAlflVeEy7R25dupxTNECZN5QMI0qNT6eT+EgaGdZcKhGkr5SdoaWiLJ3spLqIY9VCeSGrwmtg4kw==", "cpu": [ - "riscv64" + "x64" ], "dev": true, "license": "MIT", "optional": true, "os": [ - "linux" - ] + "freebsd" + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.61.1.tgz", - "integrity": "sha512-YKJ5lg35DP17gcAOggnihe+APw9HLyj1Xn7gsmGumBJAUDa6NGXNixJzmkWLhcK9TOuuyQjdamzvJefkO7qHZQ==", + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.3.3.tgz", + "integrity": "sha512-aAYUprJAJQWWbRrPvtjdroZ56Md+JM8pMiopS6xGEwDfLhqj+2ver2p4nU4Mb3CRqcMmNBjo8KkUgcxhkzVQGQ==", "cpu": [ - "riscv64" + "arm" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.61.1.tgz", - "integrity": "sha512-Mlil5G2Jj6a7B3LWGctg+XPL9vdXYuzCtNXfxOQ0nPjc2m6ueUktocPGH9bnAM0bNRKb/bAWTujUU7IJQdQA+g==", + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.3.3.tgz", + "integrity": "sha512-nDxldcEENOxZRzC2uu9jrutZdAAQtb+8WWDCSnWL1zvBk1+FN+x6MtDViPB5AJMfttVCUhehGWus3XBPgatM/w==", "cpu": [ - "s390x" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.61.1.tgz", - "integrity": "sha512-bVWIOIk6pV01p4CdUbPP7CJ/434z+OooYjDuFcR+44N35YvKUC66G8MGnvcWx5mWKW3g61J+t74l3Kj15Kwn2Q==", + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.3.3.tgz", + "integrity": "sha512-Md44bD6veX/PC5iyF8cDVnw4HBIANZepRZZ7a8DQOvkfo5WUBwcp6iAuCUz23u+4SUkhJlD3eL7hNdW8ezd/kA==", "cpu": [ - "x64" + "arm64" ], "dev": true, "license": "MIT", "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.61.1.tgz", - "integrity": "sha512-qy5pBvZbqNFheBz61R1rzsezjm0J7O2oNGoWtGoY89SZYLUfxAJTBAqDChqAIdB4rCiIbi9nF7yZ83GnNiLwSw==", + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.3.3.tgz", + "integrity": "sha512-tx7us1muwOKAKWao2v/GaafFeQboE6aj88vC6ziN2NCGcRm8gWUhwjzg+YdVB1e4boAtdtma4L43onunI6NS4w==", "cpu": [ "x64" ], @@ -1490,12 +1362,15 @@ "optional": true, "os": [ "linux" - ] + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-openbsd-x64": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.61.1.tgz", - "integrity": "sha512-E83TXjI4zm0+5f2qO+UOudaCYIhYwpJ5jq6YCZNIZ+6CbfhKrkAGezeiASBL9ElxAxFsRS9ZhESv8mfnj6TKeg==", + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.3.3.tgz", + "integrity": "sha512-SJxX60smvHgasZoBy11dX6YRjXJFovwWBoedhbQPOBzgFWBHGB+TVPWB9BxzR7TTxU8FQZAI2AyiNCMzFm8Img==", "cpu": [ "x64" ], @@ -1503,27 +1378,46 @@ "license": "MIT", "optional": true, "os": [ - "openbsd" - ] + "linux" + ], + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.61.1.tgz", - "integrity": "sha512-fbWnKqVkjrJN38vNe3ahkbk6iejS/3b0Nt7EEtPpE6RBacZcGXNKbzfHN3GUUlXOPghUg0j6XUGrtjX9z1sIvA==", + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.3.3.tgz", + "integrity": "sha512-jx1+rPhY/5Ympkktd656HBWEBLxP7dH06losBLjjf5vgCODXvi9KhtftWcMIwTFIDqBr7cRnQkdLnAG+IOlGvQ==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], "cpu": [ - "arm64" + "wasm32" ], "dev": true, "license": "MIT", "optional": true, - "os": [ - "openharmony" - ] + "dependencies": { + "@emnapi/core": "^1.11.1", + "@emnapi/runtime": "^1.11.1", + "@emnapi/wasi-threads": "^1.2.2", + "@napi-rs/wasm-runtime": "^1.1.4", + "@tybys/wasm-util": "^0.10.2", + "tslib": "^2.8.1" + }, + "engines": { + "node": ">=14.0.0" + } }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.61.1.tgz", - "integrity": "sha512-ArMl38iVAbk0New1ogihQNY6iphLi4ZaRsa037gUzv5yeKPY8TD3Dmy4x2RNC1VztU/uqm+G+/RwFrSka3Oy2g==", + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.3.3.tgz", + "integrity": "sha512-3rc292Ca2ceK6Ulcc/bAVnTs/3nDtoPhyEKlgPv+yQJQi/JS/AMJlqzxvlDacL1nekbrcf6bTqp/jV4qgnPxNQ==", "cpu": [ "arm64" ], @@ -1532,26 +1426,15 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.61.1.tgz", - "integrity": "sha512-0mYtjHS9ucAbcATycCNK9IGBk/cCe/ma7EmSLGZdsxnOA8cjRIyU04wDpVAD9NiOfLUR9KTxdiO53uOkherqjQ==", - "cpu": [ - "ia32" ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "engines": { + "node": ">= 20" + } }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.61.1.tgz", - "integrity": "sha512-gK1iCEPfpoSG9wfBihXxvBMi8ZfcWffYkEsC/Eih+iFENTaewvNcrEQ69lIOWYO5pePHKLHHO7nq5AILGO/HQQ==", + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.3.3.tgz", + "integrity": "sha512-yJ0pwIVc/nYeGoV02WtsN8KYyLQv7kyI2wDnkezyJlGGjkd4QLwDGAwl47YpPJeuI0M0ObaXGSPjvWDPeTPggw==", "cpu": [ "x64" ], @@ -1560,26 +1443,29 @@ "optional": true, "os": [ "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.61.1.tgz", - "integrity": "sha512-X+zaP2x+j4RXGfbp/seSoRHWnPxzApilDszisZxbYH5C/jTxFhCtDNdPGZb9lJyYPs24wGxruPF7Y+sIXt9Gzw==", - "cpu": [ - "x64" ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.3.3.tgz", + "integrity": "sha512-JTSZZGQi1AyKirbLN3azmjVzef92tcX7h+iSqPdaeStyFpGpDlKvvpxeOE8njhbUanbRwr3z8DyzhICWnMtQeg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.3.3", + "@tailwindcss/oxide": "4.3.3", + "postcss": "^8.5.16", + "tailwindcss": "4.3.3" + } }, "node_modules/@tanstack/query-core": { - "version": "5.101.0", - "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.101.0.tgz", - "integrity": "sha512-cQetA74EB+seWySv1TTKr828TnP0u39m6LykwDXIo84SNortpDkp30TMEjkqtYCNP9c40uT/iwl6MLiufEt0Ow==", + "version": "5.102.8", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.102.8.tgz", + "integrity": "sha512-ZNjkJ33CqvPNec/6lZBnHqLc3EVGPZ9ySLhYahU9TcuRFdmwXewuj0c4hwSWcGHqEUwcSrKeZ+oGcvPBqXcQcg==", "license": "MIT", "funding": { "type": "github", @@ -1587,12 +1473,12 @@ } }, "node_modules/@tanstack/react-query": { - "version": "5.101.0", - "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.101.0.tgz", - "integrity": "sha512-rLlJXSpkqfizLWgkR5+eLeIk0MvTx/meEIR7LRjxic+qxiQP8zVjq7BqQkiCMNLQBlLfuOLqqr6KO5GtrDlmSg==", + "version": "5.102.8", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.102.8.tgz", + "integrity": "sha512-TYBea4OuXWD7MhaSHq069TWbFe7rcwWN6kzT7JF0OKi1K6c1gTv2IzD6A6ExJsCMozdkqBWeuIUZmu4KQg0O5A==", "license": "MIT", "dependencies": { - "@tanstack/query-core": "5.101.0" + "@tanstack/query-core": "5.102.8" }, "funding": { "type": "github", @@ -1624,9 +1510,9 @@ } }, "node_modules/@testing-library/react": { - "version": "16.3.2", - "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.2.tgz", - "integrity": "sha512-XU5/SytQM+ykqMnAnvB2umaJNIOsLF3PVv//1Ew4CTcpz0/BRyy/af40qqrt7SjKpDdT1saBMc42CUok5gaw+g==", + "version": "16.3.3", + "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.3.3.tgz", + "integrity": "sha512-Uo193NgQbPMz6lrrhtRQQFcMC6Re/ELLFbbuVL30WDlZxlpZf9/lMHTAVxPRLw1q1iu9OJmR1c2BLiENRstdBg==", "dev": true, "license": "MIT", "dependencies": { @@ -1659,50 +1545,30 @@ "license": "MIT", "peer": true }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "node_modules/@types/chai": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.3.tgz", + "integrity": "sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "@types/deep-eql": "*", + "assertion-error": "^2.0.1" } }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } + "license": "MIT" }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "node_modules/@types/esrecurse": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz", + "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } + "license": "MIT" }, "node_modules/@types/estree": { "version": "1.0.9", @@ -1711,10 +1577,17 @@ "dev": true, "license": "MIT" }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/node": { - "version": "20.19.42", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.42.tgz", - "integrity": "sha512-5L7SUaFC1RyDraj2yRhyBzHTobyXHmohD100CChNtyPyleoq37Mqab5Gn8XEKI04dfN/oqPdpHk38MgcQWHbZg==", + "version": "22.20.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.20.2.tgz", + "integrity": "sha512-xlvWf4Vs9n1PEVYwP1n4vvG07M6y8WgvJ2t0vbrWTmijsIHp1cS+uJ2kMIRdY3nHZK0nCYKrPeD171+SzF4/zw==", "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -1724,6 +1597,7 @@ "version": "5.5.2", "resolved": "https://registry.npmjs.org/@types/papaparse/-/papaparse-5.5.2.tgz", "integrity": "sha512-gFnFp/JMzLHCwRf7tQHrNnfhN4eYBVYYI897CGX4MY1tzY9l2aLkVyx2IlKZ/SAqDbB3I1AOZW5gTMGGsqWliA==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -1757,122 +1631,159 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.18.0.tgz", - "integrity": "sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.70.0.tgz", + "integrity": "sha512-/v8HZt6RlyIZxB3ntehELOcUcfxKPVGWXnQdJuHRmzrqgF8nQypcC/oxGW+Ot4VGKDq81XugPKxx0n5PBtf9PA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/type-utils": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "graphemer": "^1.4.0", - "ignore": "^5.3.1", + "@eslint-community/regexpp": "^4.12.2", + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/type-utils": "8.70.0", + "@typescript-eslint/utils": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", + "ignore": "^7.0.5", "natural-compare": "^1.4.0", - "ts-api-utils": "^1.3.0" + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.70.0", + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.9", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.9.tgz", + "integrity": "sha512-brTTsvFRt5C1gGHtPst/281UjPD5t9fBqbgoMPlVWy11ZLTPfu7HxK4ZYqO9H7o/yC9rSTCI85EaQ4OoY12qYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.18.0.tgz", - "integrity": "sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.70.0.tgz", + "integrity": "sha512-zYvrmj9Yxd63UGaXw+kdt6A0F0s0qveJyuatIM77bYC2DE4pgmg7a50u8LR7PRtXd0x+h+Tl3eXabGm06SWd3Q==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4" + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", + "debug": "^4.4.3" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.70.0.tgz", + "integrity": "sha512-hFHbTNqhU9G+2eKFXCBVb1tjFT/LceiJ4+HfLO4pTpDI0KHi6iajpcFFkaSQ9gXmCh7n82A0PthaayEdN6mspQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.70.0", + "@typescript-eslint/types": "^8.70.0", + "debug": "^4.4.3" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.18.0.tgz", - "integrity": "sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.70.0.tgz", + "integrity": "sha512-8nP3Kwh5hlgZ4FicGvmznAmJe8UL4sdU8tLukrPaMuQmDuk4Y8xYfzu/aYZW4xT2JCgc7H/TpDI5cGlxcWJSqQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0" + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.70.0.tgz", + "integrity": "sha512-adnkeeNq9Sq1sUf4+FRVc0KdgYghzsgFpZSQVZVvY0LCuUuN0FnQgyGzCJeC4fW1cdXseBAjU2EOqUIjbNcZUw==", + "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.18.0.tgz", - "integrity": "sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.70.0.tgz", + "integrity": "sha512-NUMKIhYVaVIVLnRL9CRt+VVcuLgSHUCpXn4/+K8wql+vdInUzvx8BjUO1oJ7cG9shjFJKtF8F8Hh2kCh3/KBVw==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.18.0", - "@typescript-eslint/utils": "7.18.0", - "debug": "^4.3.4", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/utils": "8.70.0", + "debug": "^4.4.3", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.70.0.tgz", + "integrity": "sha512-asTOIYhDg4zdzOScCyaytrsV3cR6B4ecPQlXw/dJIm7J/MZTtCtfVII9JD8Geh4jTCrK/Xe6cg5UevoleMcoJQ==", "dev": true, "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1880,136 +1791,136 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.70.0.tgz", + "integrity": "sha512-d9NmHMPEKQ7QCLLm1jI3zmoQBwT5KwFYjXBJ9ymZfKCUU+5rmTRykKAFvH5Qn/ZCds3CEAFS9OC9M/jkl0X2bA==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" + "@typescript-eslint/project-service": "8.70.0", + "@typescript-eslint/tsconfig-utils": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/visitor-keys": "8.70.0", + "debug": "^4.4.3", + "minimatch": "^10.2.2", + "semver": "^7.7.3", + "tinyglobby": "^0.2.15", + "ts-api-utils": "^2.5.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, "node_modules/@typescript-eslint/utils": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.18.0.tgz", - "integrity": "sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.70.0.tgz", + "integrity": "sha512-oZmtKJz/4fufZ2p3+Cn3ijEojcdfR+1zYDH2xKYrEly0dR/Q/1xUPRCOlKGxod78nWlU2UnDe09GZ3TaknBFGA==", "dev": true, "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.18.0", - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/typescript-estree": "7.18.0" + "@eslint-community/eslint-utils": "^4.9.1", + "@typescript-eslint/scope-manager": "8.70.0", + "@typescript-eslint/types": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.70.0.tgz", + "integrity": "sha512-BoC8PiO4Hkdo0TVJh9Ntxr5MxPDI7/oFsrygN5ADelFSeXG/qgNuucIGA+L5Z6JpPTE/uRfcTWtscjbUaufepQ==", "dev": true, "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" + "@typescript-eslint/types": "8.70.0", + "eslint-visitor-keys": "^5.0.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.1.tgz", - "integrity": "sha512-mUFwbeTqrVgDQxFveS+df2yfap6iuP20NAKAsBt5jDEoOTDew+zwLAOilHCeQJOVSvmgCX4ogqIrA0mnyr08yQ==", - "dev": true, - "license": "ISC" - }, "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-6.1.1.tgz", + "integrity": "sha512-yxLaQV9gkhS8ezJqCM6+ndU7mDY6gqAg75NQ+0IjwEI8IYOmQCgkRwHKVSfWXW076DsqMo0Dk+0FK1U+M5RgFw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" + "@rolldown/pluginutils": "^1.0.1" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": "^20.19.0 || >=22.12.0" }, "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/@vitest/expect": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.9.tgz", - "integrity": "sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "tinyrainbow": "^1.2.0" + "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", + "babel-plugin-react-compiler": "^1.0.0", + "oxc-transform-react": "^0.145.0", + "vite": "^8.0.0" }, - "funding": { - "url": "https://opencollective.com/vitest" + "peerDependenciesMeta": { + "@rolldown/plugin-babel": { + "optional": true + }, + "babel-plugin-react-compiler": { + "optional": true + }, + "oxc-transform-react": { + "optional": true + } } }, "node_modules/@vitest/mocker": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.9.tgz", - "integrity": "sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-5.0.0.tgz", + "integrity": "sha512-66PGTMIiVJP3t4a5yxU9qPtf7MdTBs8jmToMvy+HVflB3Yy13WJZTtPePdvU+wjRV02SKK5doLbSA6o9pwOmiA==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/spy": "2.1.9", + "@jridgewell/trace-mapping": "0.3.31", + "@vitest/spy": "5.0.0", "estree-walker": "^3.0.3", - "magic-string": "^0.30.12" + "magic-string": "^1.2.3" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "msw": "^2.4.9", - "vite": "^5.0.0" + "vite": "^6.0.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "msw": { @@ -2020,80 +1931,30 @@ } } }, - "node_modules/@vitest/pretty-format": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.9.tgz", - "integrity": "sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^1.2.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.9.tgz", - "integrity": "sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "2.1.9", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.9.tgz", - "integrity": "sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==", + "node_modules/@vitest/mocker/node_modules/magic-string": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.3.1.tgz", + "integrity": "sha512-rm91zr2Ou+XueDTohjQQjdQEcYM6zVi8KVUCG8Ec3vHwUEKrhSdCNyfuIywkA6hcCAteIn0ZOtAHA6eGpiX+Pg==", "dev": true, "license": "MIT", "dependencies": { - "@vitest/pretty-format": "2.1.9", - "magic-string": "^0.30.12", - "pathe": "^1.1.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" + "@jridgewell/sourcemap-codec": "^1.6.0" } }, "node_modules/@vitest/spy": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.9.tgz", - "integrity": "sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.9.tgz", - "integrity": "sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-5.0.0.tgz", + "integrity": "sha512-uy+luWBAPw9XfthoHi5AkfHUnuPYEESjl0p/r+meoBnU8bxg5GDQ3Ey8MjcJ6sqahkL4PFyrvfMJJBw7LbU06g==", "dev": true, "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "2.1.9", - "loupe": "^3.1.2", - "tinyrainbow": "^1.2.0" - }, "funding": { "url": "https://opencollective.com/vitest" } }, "node_modules/acorn": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", - "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "dev": true, "license": "MIT", "bin": { @@ -2156,54 +2017,25 @@ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", "dev": true, "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, + "peer": true, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", @@ -2222,16 +2054,6 @@ "dequal": "^2.0.3" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/assertion-error": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", @@ -2242,61 +2064,20 @@ "node": ">=12" } }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/autoprefixer": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz", - "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==", + "node_modules/balanced-match": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-4.0.4.tgz", + "integrity": "sha512-BLrgEcRTwX2o6gGxGOCNyMvGSp35YofuYzw9h1IMTRmKqttAZZVU67bdb9Pr2vUHA8+j3i2tJfjO6C6+4myGTA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", - "dependencies": { - "browserslist": "^4.28.2", - "caniuse-lite": "^1.0.30001787", - "fraction.js": "^5.3.4", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" + "node": "18 || 20 || >=22" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, "node_modules/baseline-browser-mapping": { - "version": "2.11.22", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.22.tgz", - "integrity": "sha512-pWc4w51fBFd7mav43/zKRC+RI6f4yfzQoVlfvE8dECePyfkn1bzLp01Fj0QACcyCZyFhiEMyD2qScfKRWgWibA==", + "version": "2.11.23", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.23.tgz", + "integrity": "sha512-le521dGVfxM7yRX0EikCoSz+rOK+hHzdDt/E7mG1jOJB/6WAAUuwVroLwaB7ApaUsz5Q0kFlDXLSA9MheUIfRQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -2306,40 +2087,27 @@ "node": ">=6.0.0" } }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "node_modules/bidi-js": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.1.0.tgz", + "integrity": "sha512-fX1Onk0tdVPC7obPWB5EbJ1z7NVhLq4m2xZLq2YXBkxzMXIGRpNMU88n0EPgWseKl12J7zXs7qrDxPK4sRs2fg==", "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "require-from-string": "^2.0.2" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/brace-expansion": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-5.0.9.tgz", + "integrity": "sha512-ScQ4IuvIEF1TMlP7Zt+vjJ//9zlPb2SDcxWxM3bk8s6t6GGdJ7KO1dCcTidOPJKePW30LE/2cT7wCyPho9/Wxg==", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" + "balanced-match": "^4.0.2" }, "engines": { - "node": ">=8" + "node": "20 || >=22" } }, "node_modules/browserslist": { @@ -2376,48 +2144,18 @@ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", - "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "node_modules/cacheable": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/cacheable/-/cacheable-2.5.0.tgz", + "integrity": "sha512-60cyAOytib/OzBw1JNSoSV/boK1AtHryDIjvVBk7XbN4ugfkM3+Sry7fEjNgPMGgOjuaZPAp8ruZ0Cxafwyq9g==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" + "@cacheable/memory": "^2.2.0", + "@cacheable/utils": "^2.5.0", + "hookified": "^1.15.0", + "keyv": "^5.6.0", + "qified": "^0.10.1" } }, "node_modules/caniuse-lite": { @@ -2442,39 +2180,15 @@ "license": "CC-BY-4.0" }, "node_modules/chai": { - "version": "5.3.3", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", - "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/chai/-/chai-6.2.2.tgz", + "integrity": "sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg==", "dev": true, "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, "engines": { "node": ">=18" } }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/change-case": { "version": "5.4.4", "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", @@ -2482,74 +2196,6 @@ "dev": true, "license": "MIT" }, - "node_modules/check-error": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.3.tgz", - "integrity": "sha512-PAJdDJusoxnwm1VwW07VWwUN1sl7smmC3OKggvndJFadxxDRyFJBX/ggnu/KE4kQAB7a3Dp8f/YXC1FlUprWmA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, "node_modules/colorette": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", @@ -2557,36 +2203,6 @@ "dev": true, "license": "MIT" }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -2594,6 +2210,19 @@ "dev": true, "license": "MIT" }, + "node_modules/cookie": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.1.1.tgz", + "integrity": "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -2609,40 +2238,20 @@ "node": ">= 8" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/cssstyle": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-4.6.0.tgz", - "integrity": "sha512-2z+rWdzbbSZv6/rhtvzvqeZQHrBaqgogqt85sqFNbabZOuFbCVFb8kPeEtZjiKkbrm395irpNKiYeFeLiQnFPg==", + "node_modules/css-tree": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.2.1.tgz", + "integrity": "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA==", "dev": true, "license": "MIT", "dependencies": { - "@asamuzakjp/css-color": "^3.2.0", - "rrweb-cssom": "^0.8.0" + "mdn-data": "2.27.1", + "source-map-js": "^1.2.1" }, "engines": { - "node": ">=18" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/cssstyle/node_modules/rrweb-cssom": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.8.0.tgz", - "integrity": "sha512-guoltQEx+9aMf2gDZ0s62EcV8lsXR+0w8915TC3ITdn2YueuNjdAYh/levpU9nFaoChh9RUS5ZdQMrKfVEN9tw==", - "dev": true, - "license": "MIT" - }, "node_modules/csstype": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", @@ -2651,17 +2260,32 @@ "license": "MIT" }, "node_modules/data-urls": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-5.0.0.tgz", - "integrity": "sha512-ZYP5VBHshaDAiVZxjbRVcFJpc+4xGgT0bK3vzy1HLN8jTO975HEbuYzZJcHoQEY5K1a0z8YayJkyVETa08eNTg==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-7.0.0.tgz", + "integrity": "sha512-23XHcCF+coGYevirZceTVD7NdJOqVn+49IHyxgszm+JIiHLoB2TkmPtsYkNWT1pvRSGkc35L6NHs0yHkN2SumA==", "dev": true, "license": "MIT", "dependencies": { - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0" + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^16.0.0" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "16.0.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-16.0.1.tgz", + "integrity": "sha512-1to4zXBxmXHV3IiSSEInrreIlu02vUOvrhxJJH5vcxYTBDAx51cqZiKdyTxlecdKNSjj8EcxGBxNf6Vg+945gw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@exodus/bytes": "^1.11.0", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" + }, + "engines": { + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/debug": { @@ -2689,16 +2313,6 @@ "dev": true, "license": "MIT" }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/deep-is": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", @@ -2706,16 +2320,6 @@ "dev": true, "license": "MIT" }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/dequal": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", @@ -2727,44 +2331,14 @@ "node": ">=6" } }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, - "license": "MIT" - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", "dev": true, "license": "Apache-2.0", - "dependencies": { - "esutils": "^2.0.2" - }, "engines": { - "node": ">=6.0.0" + "node": ">=8" } }, "node_modules/dom-accessibility-api": { @@ -2775,136 +2349,47 @@ "license": "MIT", "peer": true }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" - } - }, "node_modules/electron-to-chromium": { "version": "1.5.427", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.427.tgz", "integrity": "sha512-n14zb3FdsChZ2BNobqNHAJMcP3ifFv4paox2LvCrfVAQcqGiSURgbJl+PfMpHVCNFkStnNc+RRVtPBTVW5PDgw==", "dev": true, - "license": "ISC" - }, - "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "dev": true, - "license": "MIT" - }, - "node_modules/es-object-atoms": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", - "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0" - }, - "engines": { - "node": ">= 0.4" - } + "license": "ISC" }, - "node_modules/es-set-tostringtag": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", - "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "node_modules/enhanced-resolve": { + "version": "5.25.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.25.0.tgz", + "integrity": "sha512-ghq3mhs649mvbarTCAlZn2wRhbfHmzAFiKxoWA14B3VtqnxtZt+wz8BroKXU0tF3GiJsnUldjVncQGZ8qk4rdA==", "dev": true, "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" }, "engines": { - "node": ">= 0.4" + "node": ">=10.13.0" } }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "node_modules/entities": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-8.1.0.tgz", + "integrity": "sha512-kxL7msIffSuh9aaFAMD7rxAIuTRMAHMeBtgHW2yUdWw732ZNh4MehkF2gdjvtdmikkaIP9bFDDJOPlsvm7avrA==", "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, + "license": "BSD-2-Clause", "engines": { - "node": ">=12" + "node": ">=20.19.0" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, + "node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "dev": true, + "license": "MIT" + }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", @@ -2929,152 +2414,139 @@ } }, "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "version": "10.10.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-10.10.0.tgz", + "integrity": "sha512-NPXn6r5zl4uET1DAVPaOwzX3rut4c0wcmw3dWJAfOsTM5+TogXo0DDjz8pwm/hL8cyVNpHqeK4JpN0NjnyFFNw==", "dev": true, "license": "MIT", + "workspaces": [ + "packages/*" + ], "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.2", + "@eslint/config-array": "^0.23.5", + "@eslint/config-helpers": "^0.7.0", + "@eslint/core": "^1.2.1", + "@eslint/plugin-kit": "^0.7.3", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^9.1.2", + "eslint-visitor-keys": "^5.0.1", + "espree": "^11.2.0", + "esquery": "^1.7.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "11.1.5 || >11.1.6 <12", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", + "minimatch": "^10.2.5", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-plugin-react-hooks": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", - "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.1.1.tgz", + "integrity": "sha512-f2I7Gw6JbvCexzIInuSbZpfdQ44D7iqdWX01FKLvrPgqxoE7oMj8clOfto8U6vYiz4yd5oKu39rRSVOe1zRu0g==", "dev": true, "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, "engines": { - "node": ">=10" + "node": ">=18" }, "peerDependencies": { - "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0 || ^10.0.0" } }, "node_modules/eslint-plugin-react-refresh": { - "version": "0.4.26", - "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", - "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.5.6.tgz", + "integrity": "sha512-uZnh24On2bk478AkaDAKcpRiYhS3qFSaSNvpXxV6/Ek/BBDICkWGG7MnBSfjnIlCVBei5vsLlIeQYxbF22+Udg==", "dev": true, "license": "MIT", "peerDependencies": { - "eslint": ">=8.40" + "eslint": "^9 || ^10" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "9.1.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz", + "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { + "@types/esrecurse": "^4.3.1", + "@types/estree": "^1.0.8", "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz", + "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==", "dev": true, "license": "Apache-2.0", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" } }, - "node_modules/eslint/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/eslint/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-11.2.0.tgz", + "integrity": "sha512-7p3DrVEIopW1B1avAGLuCSh1jubc01H2JHc8B4qqGblmg5gI9yumBgACjWo4JlIc04ufug4xJ3SQI8HkS/Rgzw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.16.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^5.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^20.19.0 || ^22.13.0 || >=24" }, "funding": { "url": "https://opencollective.com/eslint" @@ -3137,9 +2609,9 @@ } }, "node_modules/expect-type": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.3.0.tgz", - "integrity": "sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.4.0.tgz", + "integrity": "sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==", "dev": true, "license": "Apache-2.0", "engines": { @@ -3153,36 +2625,6 @@ "dev": true, "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", @@ -3197,40 +2639,32 @@ "dev": true, "license": "MIT" }, - "node_modules/fastq": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", - "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", - "dependencies": { - "flat-cache": "^3.0.4" - }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/file-entry-cache": { + "version": "11.1.5", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-11.1.5.tgz", + "integrity": "sha512-+PFTHITI08JIGhnNpGNI8T8inUpgZfk3GNEqfT9R2zZV2iFXg3CvqzSl/uEhs7TSGujYRELEANyDvS8Fj7+S7Q==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" + "flat-cache": "^6.1.23" } }, "node_modules/find-up": { @@ -3251,62 +2685,21 @@ } }, "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "version": "6.1.23", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-6.1.23.tgz", + "integrity": "sha512-f++BY9pTk+983xK1FLzlLpmM0i0z+jHmx3QESGkURMXujQZz1k5wzwX6hjnQ8goaD0B+sYnDK1yZ6MTyZfUaqA==", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" + "cacheable": "^2.5.0", + "flatted": "^3.4.2", + "hookified": "^1.15.0" } }, "node_modules/flatted": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", - "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", - "dev": true, - "license": "ISC" - }, - "node_modules/form-data": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", - "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "es-set-tostringtag": "^2.1.0", - "hasown": "^2.0.4", - "mime-types": "^2.1.35" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", "dev": true, "license": "ISC" }, @@ -3325,16 +2718,6 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/gensync": { "version": "1.0.0-beta.2", "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", @@ -3345,67 +2728,6 @@ "node": ">=6.9.0" } }, - "node_modules/get-intrinsic": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", - "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "call-bind-apply-helpers": "^1.0.2", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.1.1", - "function-bind": "^1.1.2", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", - "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", - "dev": true, - "license": "MIT", - "dependencies": { - "dunder-proto": "^1.0.1", - "es-object-atoms": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -3419,173 +2741,83 @@ "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", - "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "version": "17.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-17.12.0.tgz", + "integrity": "sha512-cezEd/DTyyht9cvSSURyygXPfy04GtWO/5e6ZPvH7fCtjKz9PYOmuawphw1Ctd1f6C+5JypXfGD7ahNMXvevBA==", "dev": true, "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, "engines": { - "node": ">=8" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } + "license": "ISC" }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "node_modules/hashery": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/hashery/-/hashery-1.5.1.tgz", + "integrity": "sha512-iZyKG96/JwPz1N55vj2Ie2vXbhu440zfUfJvSwEqEbeLluk7NnapfGqa7LH0mOsnDxTF85Mx8/dyR6HfqcbmbQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "hookified": "^1.15.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true, - "license": "MIT" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=8" + "node": ">=20" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "license": "MIT" }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", "dev": true, "license": "MIT", "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "hermes-estree": "0.25.1" } }, - "node_modules/hasown": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", - "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "node_modules/hookified": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-1.15.1.tgz", + "integrity": "sha512-MvG/clsADq1GPM2KGo2nyfaWVyn9naPiXrqIe4jYjXNZQt238kWyOGrsyc/DmRAQ+Re6yeo6yX/yoNCG5KAEVg==", "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } + "license": "MIT" }, "node_modules/html-encoding-sniffer": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-4.0.0.tgz", - "integrity": "sha512-Y22oTqIU4uuPgEemfz7NDJz6OeKf12Lsu+QC+s3BVpda64lTiMYCyGwg5ki4vFxkMwQdeZDl2adZoqUgdFuTgQ==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/html-encoding-sniffer/-/html-encoding-sniffer-6.0.0.tgz", + "integrity": "sha512-CV9TW3Y3f8/wT0BRFc1/KAVQ3TUHiXmaAb6VW9vtiMFf7SLoMd1PdAc4W3KFOFETBJUb90KatHqlsZMWV+R9Gg==", "dev": true, "license": "MIT", "dependencies": { - "whatwg-encoding": "^3.1.1" + "@exodus/bytes": "^1.6.0" }, "engines": { - "node": ">=18" + "node": "^20.19.0 || ^22.12.0 || >=24.0.0" } }, "node_modules/html-parse-stringify": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.1.0.tgz", - "integrity": "sha512-E0oAXcELOtsXe+BmpJ2EZyedbldPpriV5vICzEuo6xjC/D1lDukOI7KrpfQGF2Qc4wWEy0nk3bFORS2K5ZAhFQ==", - "license": "MIT", - "dependencies": { - "void-elements": "3.1.0" - } - }, - "node_modules/http-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", - "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", - "dev": true, + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-4.0.1.tgz", + "integrity": "sha512-0zHsZJrK7S3K2aucXWL6ycoYJ/iNtIcFHC/nYQgFklPtrv5LpJctIiSCroWZWeuoXvuyFdzp6KzjJQ+OT5MfFw==", "license": "MIT", - "dependencies": { - "agent-base": "^7.1.0", - "debug": "^4.3.4" - }, - "engines": { - "node": ">= 14" + "funding": { + "url": "https://locize.com" } }, "node_modules/https-proxy-agent": { @@ -3603,75 +2835,50 @@ } }, "node_modules/i18next": { - "version": "23.16.8", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", - "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", + "version": "26.4.2", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-26.4.2.tgz", + "integrity": "sha512-RX+R0VLg13IbvRuJSxnqykUFS9vQZTl8wYpWPCIUDWVrSGjsQywB5Y+pjzrkboxGAuYfJZVH1InFTdgBdxq6ug==", "funding": [ { "type": "individual", - "url": "https://locize.com" + "url": "https://www.locize.com/i18next" }, { "type": "individual", - "url": "https://locize.com/i18next.html" + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" }, { "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + "url": "https://www.locize.com" } ], "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.2" + "peerDependencies": { + "typescript": "^5 || ^6 || ^7" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/i18next-browser-languagedetector": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.2.tgz", - "integrity": "sha512-6b7r75uIJDWCcCflmbof+sJ94k9UQO4X0YR62oUfqGI/GjCLVzlCwu8TFdRZIqVLzWbzNcmkmhfqKEr4TLz4HQ==", + "version": "8.2.1", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-8.2.1.tgz", + "integrity": "sha512-bZg8+4bdmaOiApD7N7BPT9W8MLZG+nPTOFlLiJiT8uzKXFjhxw4v2ierCXOwB5sFDMtuA5G4kgYZ0AznZxQ/cw==", "license": "MIT", "dependencies": { "@babel/runtime": "^7.23.2" } }, - "node_modules/iconv-lite": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", - "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", - "dev": true, - "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/imurmurhash": { @@ -3697,54 +2904,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.16.2", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", - "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -3768,26 +2927,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/is-potential-custom-element-name": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.1.tgz", @@ -3803,13 +2942,13 @@ "license": "ISC" }, "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.7.0.tgz", + "integrity": "sha512-AC/7JofJvZGrrneWNaEnJeOLUx+JlGt7tNa0wZiRPT4MY1wmfKjt2+6O2p2uz2+skll8OZZmJMNqeke7kKbNgQ==", "dev": true, "license": "MIT", "bin": { - "jiti": "bin/jiti.js" + "jiti": "lib/jiti-cli.mjs" } }, "node_modules/js-levenshtein": { @@ -3852,39 +2991,39 @@ } }, "node_modules/jsdom": { - "version": "24.1.3", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-24.1.3.tgz", - "integrity": "sha512-MyL55p3Ut3cXbeBEG7Hcv0mVM8pp8PBNWxRqchZnSfAiES1v1mRnMeFfaHWIPULpwsYfvO+ZmMZz5tGCnjzDUQ==", + "version": "30.0.1", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-30.0.1.tgz", + "integrity": "sha512-52v7mUVUfNQVYYqE1lcdaymWL0njO7lTLUog6ZvW2U5KsbiLk/GnZlVJ+qx0xfNJZ6Gn+KSpPNE52vurbxZwrA==", "dev": true, "license": "MIT", "dependencies": { - "cssstyle": "^4.0.1", - "data-urls": "^5.0.0", - "decimal.js": "^10.4.3", - "form-data": "^4.0.0", - "html-encoding-sniffer": "^4.0.0", - "http-proxy-agent": "^7.0.2", - "https-proxy-agent": "^7.0.5", + "@asamuzakjp/css-color": "^6.0.5", + "@asamuzakjp/dom-selector": "^8.3.0", + "@bramus/specificity": "^2.4.2", + "@csstools/css-syntax-patches-for-csstree": "^1.1.7", + "@exodus/bytes": "^1.15.1", + "css-tree": "^3.2.1", + "data-urls": "^7.0.0", + "decimal.js": "^10.6.0", + "html-encoding-sniffer": "^6.0.0", "is-potential-custom-element-name": "^1.0.1", - "nwsapi": "^2.2.12", - "parse5": "^7.1.2", - "rrweb-cssom": "^0.7.1", + "lru-cache": "^11.5.2", + "parse5": "^8.0.1", "saxes": "^6.0.0", "symbol-tree": "^3.2.4", - "tough-cookie": "^4.1.4", + "tough-cookie": "^6.0.2", + "undici": "^8.9.0", "w3c-xmlserializer": "^5.0.0", - "webidl-conversions": "^7.0.0", - "whatwg-encoding": "^3.1.1", - "whatwg-mimetype": "^4.0.0", - "whatwg-url": "^14.0.0", - "ws": "^8.18.0", + "webidl-conversions": "^8.0.1", + "whatwg-mimetype": "^5.0.0", + "whatwg-url": "^17.1.0", "xml-name-validator": "^5.0.0" }, "engines": { - "node": ">=18" + "node": "^22.22.2 || ^24.15.0 || >=26.0.0" }, "peerDependencies": { - "canvas": "^2.11.2" + "canvas": "^3.2.3" }, "peerDependenciesMeta": { "canvas": { @@ -3892,6 +3031,16 @@ } } }, + "node_modules/jsdom/node_modules/lru-cache": { + "version": "11.5.2", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.5.2.tgz", + "integrity": "sha512-4pfM1Ff0x50o0tQwb5ucw/RzNyD0/YJME6IVcStalZuMWxdt3sR3huStTtxz4PUmvZfRguvDejasvQ2kifR11g==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/jsesc": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", @@ -3905,13 +3054,6 @@ "node": ">=6" } }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true, - "license": "MIT" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -3940,13 +3082,13 @@ } }, "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-5.6.0.tgz", + "integrity": "sha512-CYDD3SOtsHtyXeEORYRx2qBtpDJFjRTGXUtmNEMGyzYOKj1TE3tycdlho7kA1Ufx9OYWZzg52QFBGALTirzDSw==", "dev": true, "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "@keyv/serialize": "^1.1.1" } }, "node_modules/levn": { @@ -3963,25 +3105,266 @@ "node": ">= 0.8.0" } }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "node_modules/lightningcss": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.32.0.tgz", + "integrity": "sha512-NXYBzinNrblfraPGyrbPoD19C1h9lfI/1mzgWYvXUTe414Gz/X1FD2XBZSZM7rRTrMA8JL3OtAaGifrIKhQ5yQ==", "dev": true, - "license": "MIT", + "license": "MPL-2.0", + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "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" + } + }, + "node_modules/lightningcss-android-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.32.0.tgz", + "integrity": "sha512-YK7/ClTt4kAK0vo6w3X+Pnm0D2cf2vPHbhOXdoNti1Ga0al1P4TBZhwjATvjNwLEBCnKvjJc2jQgHXH0NEwlAg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=14" + "node": ">= 12.0.0" }, "funding": { - "url": "https://github.com/sponsors/antonk52" + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "node_modules/lightningcss-darwin-arm64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.32.0.tgz", + "integrity": "sha512-RzeG9Ju5bag2Bv1/lwlVJvBE3q6TtXskdZLLCyfg5pt+HLz9BqlICO7LZM7VHNTTn/5PRhHFBSjk5lc4cmscPQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.32.0.tgz", + "integrity": "sha512-U+QsBp2m/s2wqpUYT/6wnlagdZbtZdndSmut/NJqlCcMLTWp5muCrID+K5UJ6jqD2BFshejCYXniPDbNh73V8w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.32.0.tgz", + "integrity": "sha512-JCTigedEksZk3tHTTthnMdVfGf61Fky8Ji2E4YjUTEQX14xiy/lTzXnu1vwiZe3bYe0q+SpsSH/CTeDXK6WHig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.32.0.tgz", + "integrity": "sha512-x6rnnpRa2GL0zQOkt6rts3YDPzduLpWvwAF6EMhXFVZXD4tPrBkEFqzGowzCsIWsPjqSK+tyNEODUBXeeVHSkw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.32.0.tgz", + "integrity": "sha512-0nnMyoyOLRJXfbMOilaSRcLH3Jw5z9HDNGfT/gwCPgaDjnx0i8w7vBzFLFR1f6CMLKF8gVbebmkUN3fa/kQJpQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.32.0.tgz", + "integrity": "sha512-UpQkoenr4UJEzgVIYpI80lDFvRmPVg6oqboNHfoH4CQIfNA+HOrZ7Mo7KZP02dC6LjghPQJeBsvXhJod/wnIBg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.32.0.tgz", + "integrity": "sha512-V7Qr52IhZmdKPVr+Vtw8o+WLsQJYCTd8loIfpDaMRWGUZfBOYEJeyJIkqGIDMZPwPx24pUMfwSxxI8phr/MbOA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.32.0.tgz", + "integrity": "sha512-bYcLp+Vb0awsiXg/80uCRezCYHNg1/l3mt0gzHnWV9XP1W5sKa5/TCdGWaR/zBM2PeF/HbsQv/j2URNOiVuxWg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.32.0.tgz", + "integrity": "sha512-8SbC8BR40pS6baCM8sbtYDSwEVQd4JlFTOlaD3gWGHfThTcABnNDBda6eTZeqbofalIJhFx0qKzgHJmcPTnGdw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.32.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.32.0.tgz", + "integrity": "sha512-Amq9B/SoZYdDi1kFrojnoqPLxYhQ4Wo5XiL8EVJrVsB8ARoC1PWW6VGtT0WKCemjy8aC+louJnjS7U18x3b06Q==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } }, "node_modules/locate-path": { "version": "6.0.0", @@ -3999,13 +3382,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true, - "license": "MIT" - }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -4018,13 +3394,6 @@ "loose-envify": "cli.js" } }, - "node_modules/loupe": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", - "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", - "dev": true, - "license": "MIT" - }, "node_modules/lru-cache": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", @@ -4056,74 +3425,24 @@ "@jridgewell/sourcemap-codec": "^1.5.5" } }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "node_modules/mdn-data": { + "version": "2.27.1", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.27.1.tgz", + "integrity": "sha512-9Yubnt3e8A0OKwxYSXyhLymGW4sCufcLG6VdiDdUGVkPhpqLxlvP5vl1983gQjJl3tqbrM731mjaZaP68AgosQ==", "dev": true, - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } + "license": "CC0-1.0" }, "node_modules/minimatch": { - "version": "9.0.9", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", - "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "version": "10.2.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.2.6.tgz", + "integrity": "sha512-vpLQEs+VLCr1nU0BXS07maYoFwlDAH0gngQuuttxIwutDFEMHq2blX+8vpgxDdK3J1PwjCJiep77OitTZ4Ll1A==", "dev": true, - "license": "ISC", + "license": "BlueOak-1.0.0", "dependencies": { - "brace-expansion": "^2.0.2" + "brace-expansion": "^5.0.8" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": "18 || 20 || >=22" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -4134,19 +3453,7 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } + "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.19", @@ -4184,51 +3491,18 @@ "node": ">=18" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nwsapi": { - "version": "2.2.24", - "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.24.tgz", - "integrity": "sha512-7YRhZ3jS45LwmSCT4b2sVFHt/WuovaktDU07QrtOBY2PXskss5a9jfmR9jptyumwXST+rFjrmppMY1KT/yn35A==", - "dev": true, - "license": "MIT" - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "node_modules/obug": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/obug/-/obug-2.2.1.tgz", + "integrity": "sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==", "dev": true, + "funding": [ + "https://github.com/sponsors/sxzz", + "https://opencollective.com/debug" + ], "license": "MIT", "engines": { - "node": ">= 6" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" + "node": ">=12.20.0" } }, "node_modules/openapi-fetch": { @@ -4267,19 +3541,6 @@ "integrity": "sha512-xofUHlVFq+BMquf3nh9I8N2guHckW6mrDO/F3kaFgrL7MGbjldDnQ9TIT+rkH/+H0LiuO+RuZLnNmsJwsjwUKg==", "license": "MIT" }, - "node_modules/openapi-typescript/node_modules/supports-color": { - "version": "10.2.2", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", - "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -4331,22 +3592,10 @@ } }, "node_modules/papaparse": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.6.0.tgz", - "integrity": "sha512-N2vuNQAYGK1/4vs6HJX86+VYU6OkiSTgdJz3JQfTk1y51cFCO/U8gnaeTF4iNE4r57Tt0sV47dUua1/19pxO6Q==" - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.7.0.tgz", + "integrity": "sha512-qBGxg/7Q3Kl9Wfhrz2Z74UnvnHTXLNG6jmKJFeBvP2+y4lV7So+7SR62+Zd47JvdrCkX+nDcnr0ObPzek/+6RA==", + "license": "MIT" }, "node_modules/parse-json": { "version": "8.3.0", @@ -4366,27 +3615,14 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/parse-json/node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-8.0.1.tgz", + "integrity": "sha512-z1e/HMG90obSGeidlli3hj7cbocou0/wa5HacvI3ASx34PecNjNQeaHNo5WIZpWofN9kgkqV1q5YvXe3F0FoPw==", "dev": true, "license": "MIT", "dependencies": { - "entities": "^6.0.0" + "entities": "^8.0.0" }, "funding": { "url": "https://github.com/inikulin/parse5?sponsor=1" @@ -4402,16 +3638,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -4422,40 +3648,6 @@ "node": ">=8" } }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/pathe": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", - "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", - "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -4464,38 +3656,18 @@ "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.7.tgz", + "integrity": "sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==", "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, "node_modules/pluralize": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", @@ -4535,140 +3707,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", - "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", - "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.1.1" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", - "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4682,7 +3720,8 @@ "node_modules/pretendard": { "version": "1.3.9", "resolved": "https://registry.npmjs.org/pretendard/-/pretendard-1.3.9.tgz", - "integrity": "sha512-PaQAADyLY5v4kYFwkpSJHbSSYIkiriY/1xXw75TKoZ9UQQqeU+tvP05yTdZAWibiIYoo8ZKtRv8PM7w0IaywSw==" + "integrity": "sha512-PaQAADyLY5v4kYFwkpSJHbSSYIkiriY/1xXw75TKoZ9UQQqeU+tvP05yTdZAWibiIYoo8ZKtRv8PM7w0IaywSw==", + "license": "OFL-1.1" }, "node_modules/pretty-format": { "version": "27.5.1", @@ -4700,71 +3739,36 @@ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" } }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", - "peer": true, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=6" } }, - "node_modules/psl": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz", - "integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==", + "node_modules/qified": { + "version": "0.10.1", + "resolved": "https://registry.npmjs.org/qified/-/qified-0.10.1.tgz", + "integrity": "sha512-+Owyggi9IxT1ePKGafcI87ubSmxol6smwJ+RAHDQlx9+9cPwFWDiKFFCPuWhr9ignlGpZ9vDQLw67N4dcTVFEA==", "dev": true, "license": "MIT", "dependencies": { - "punycode": "^2.3.1" + "hookified": "^2.1.1" }, - "funding": { - "url": "https://github.com/sponsors/lupomontero" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "license": "MIT", "engines": { - "node": ">=6" + "node": ">=20" } }, - "node_modules/querystringify": { + "node_modules/qified/node_modules/hookified": { "version": "2.2.0", - "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", - "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "resolved": "https://registry.npmjs.org/hookified/-/hookified-2.2.0.tgz", + "integrity": "sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==", "dev": true, "license": "MIT" }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -4791,17 +3795,19 @@ } }, "node_modules/react-i18next": { - "version": "14.1.3", - "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-14.1.3.tgz", - "integrity": "sha512-wZnpfunU6UIAiJ+bxwOiTmBOAaB14ha97MjOEnLGac2RJ+h/maIYXZuTHlmyqQVX1UVHmU1YDTQ5vxLmwfXTjw==", + "version": "17.0.13", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-17.0.13.tgz", + "integrity": "sha512-Cc1PscmblIHA1kljTqDwrcVMI21ydgmUzw0UAeQBe7pAOgfuRLfzXze4EUBQoeDiICzFIXXhHFoZxuetNg5D0Q==", "license": "MIT", "dependencies": { - "@babel/runtime": "^7.23.9", - "html-parse-stringify": "^3.0.1" + "@babel/runtime": "^7.29.7", + "html-parse-stringify": "^4.0.1", + "use-sync-external-store": "^1.6.0" }, "peerDependencies": { - "i18next": ">= 23.2.3", - "react": ">= 16.8.0" + "i18next": ">= 26.2.0", + "react": ">= 16.8.0", + "typescript": "^5 || ^6 || ^7" }, "peerDependenciesMeta": { "react-dom": { @@ -4809,6 +3815,9 @@ }, "react-native": { "optional": true + }, + "typescript": { + "optional": true } } }, @@ -4820,69 +3829,42 @@ "license": "MIT", "peer": true }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-router": { - "version": "6.30.6", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.6.tgz", - "integrity": "sha512-5HfK7k5im7LTOB0EqCQmfvy4C13G92Ssj1VTmouTK3AJvyjKTnFuCV0vcMAD/JS+JC4DvDIBRrlAeJIFjh5VWg==", - "license": "MIT", - "dependencies": { - "@remix-run/router": "1.23.4" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "react": ">=16.8" - } - }, - "node_modules/react-router-dom": { - "version": "6.30.6", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.6.tgz", - "integrity": "sha512-0RHKZz7wwffvkU+2MFVT2NnjK44ssLEV+m0CAJaS2Ksmorrwj7WxH00jO0SOCW26/tINUnJHToXblDs33I38YQ==", + "node_modules/react-router": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.18.3.tgz", + "integrity": "sha512-gyXgtdr5uACJ5b1Q4udzjVV+tb/rlHIMJKuJ0e89R4Kzgz47z/rgP0dIKxktqIEUhDHluGTPJJH/wRha7CyqsA==", "license": "MIT", "dependencies": { - "@remix-run/router": "1.23.4", - "react-router": "6.30.6" + "cookie": "^1.0.1", + "set-cookie-parser": "^2.6.0" }, "engines": { - "node": ">=14.0.0" + "node": ">=20.0.0" }, "peerDependencies": { - "react": ">=16.8", - "react-dom": ">=16.8" - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" + "react": ">=18", + "react-dom": ">=18" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + } } }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, + "node_modules/react-router-dom": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.18.3.tgz", + "integrity": "sha512-ytVbyBBM7vMfRCam25r0WMhSVSom909A8p+8m0/f1w853dz/xfFu6etAT2SEbVoSnI+ZoPRDqIsQXVT89gp7kg==", "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "react-router": "7.18.3" }, "engines": { - "node": ">=8.10.0" + "node": ">=20.0.0" + }, + "peerDependencies": { + "react": ">=18", + "react-dom": ">=18" } }, "node_modules/require-from-string": { @@ -4895,156 +3877,40 @@ "node": ">=0.10.0" } }, - "node_modules/requires-port": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", - "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/resolve": { - "version": "1.22.12", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", - "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", - "dev": true, - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.61.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.61.1.tgz", - "integrity": "sha512-I4KW6iuRpuu2uHBLraZ1wNZe0DP7lnRha+VJ9tNaYVaVgKhW0aI3h4RYnoRPeql0flHm/Co55b7snEDcOfOJrA==", + "node_modules/rolldown": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rolldown/-/rolldown-1.2.8.tgz", + "integrity": "sha512-Z67nTmhZe7anqnM/EjI392w5i/ANUinjip7QYsOyN37oayduxt3ksdX0hf5OOamkAd53BiIHfbfSzfUmzKFQqQ==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.9" + "@oxc-project/types": "=0.149.0", + "@rolldown/pluginutils": "^1.0.0" }, "bin": { - "rollup": "dist/bin/rollup" + "rolldown": "bin/cli.mjs" }, "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" + "node": "^20.19.0 || >=22.12.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.61.1", - "@rollup/rollup-android-arm64": "4.61.1", - "@rollup/rollup-darwin-arm64": "4.61.1", - "@rollup/rollup-darwin-x64": "4.61.1", - "@rollup/rollup-freebsd-arm64": "4.61.1", - "@rollup/rollup-freebsd-x64": "4.61.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.61.1", - "@rollup/rollup-linux-arm-musleabihf": "4.61.1", - "@rollup/rollup-linux-arm64-gnu": "4.61.1", - "@rollup/rollup-linux-arm64-musl": "4.61.1", - "@rollup/rollup-linux-loong64-gnu": "4.61.1", - "@rollup/rollup-linux-loong64-musl": "4.61.1", - "@rollup/rollup-linux-ppc64-gnu": "4.61.1", - "@rollup/rollup-linux-ppc64-musl": "4.61.1", - "@rollup/rollup-linux-riscv64-gnu": "4.61.1", - "@rollup/rollup-linux-riscv64-musl": "4.61.1", - "@rollup/rollup-linux-s390x-gnu": "4.61.1", - "@rollup/rollup-linux-x64-gnu": "4.61.1", - "@rollup/rollup-linux-x64-musl": "4.61.1", - "@rollup/rollup-openbsd-x64": "4.61.1", - "@rollup/rollup-openharmony-arm64": "4.61.1", - "@rollup/rollup-win32-arm64-msvc": "4.61.1", - "@rollup/rollup-win32-ia32-msvc": "4.61.1", - "@rollup/rollup-win32-x64-gnu": "4.61.1", - "@rollup/rollup-win32-x64-msvc": "4.61.1", - "fsevents": "~2.3.2" - } - }, - "node_modules/rrweb-cssom": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/rrweb-cssom/-/rrweb-cssom-0.7.1.tgz", - "integrity": "sha512-TrEMa7JGdVm0UThDJSx7ddw5nVm3UJS9o9CCIZ72B1vSyEZoziDqBYP3XIoi/12lKrJR8rE3jeFHMok2F/Mnsg==", - "dev": true, - "license": "MIT" - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" + "@rolldown/binding-android-arm-eabi": "1.2.8", + "@rolldown/binding-android-arm64": "1.2.8", + "@rolldown/binding-darwin-arm64": "1.2.8", + "@rolldown/binding-darwin-x64": "1.2.8", + "@rolldown/binding-freebsd-x64": "1.2.8", + "@rolldown/binding-linux-arm-gnueabihf": "1.2.8", + "@rolldown/binding-linux-arm64-gnu": "1.2.8", + "@rolldown/binding-linux-arm64-musl": "1.2.8", + "@rolldown/binding-linux-ppc64-gnu": "1.2.8", + "@rolldown/binding-linux-s390x-gnu": "1.2.8", + "@rolldown/binding-linux-x64-gnu": "1.2.8", + "@rolldown/binding-linux-x64-musl": "1.2.8", + "@rolldown/binding-openharmony-arm64": "1.2.8", + "@rolldown/binding-win32-arm64-msvc": "1.2.8", + "@rolldown/binding-win32-x64-msvc": "1.2.8" } }, - "node_modules/safer-buffer": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", - "dev": true, - "license": "MIT" - }, "node_modules/saxes": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/saxes/-/saxes-6.0.0.tgz", @@ -5068,18 +3934,21 @@ } }, "node_modules/semver": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.3.tgz", - "integrity": "sha512-wnilbGyMxzbY7dNOl7jpKbLSjcfeweJWU5j4+u5qW+6/wuGD9KzIGOyZnQVSBM9E7DtWaaH3CyHkppYrKYoxwg==", + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, + "node_modules/set-cookie-parser": { + "version": "2.7.2", + "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz", + "integrity": "sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw==", + "license": "MIT" + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -5110,16 +3979,6 @@ "dev": true, "license": "ISC" }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -5138,85 +3997,23 @@ "license": "MIT" }, "node_modules/std-env": { - "version": "3.10.0", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.10.0.tgz", - "integrity": "sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==", + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-4.2.0.tgz", + "integrity": "sha512-oCUKSupKTHX53EyjDtuZQ64pjLJ6yYCtpmEw0goYxtjG9KpbRe8KAsl2tBUGU9DyMcJ0RwJ8GqJAFzMXcXW1Rw==", "dev": true, "license": "MIT" }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/sucrase": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", - "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "tinyglobby": "^0.2.11", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-10.2.2.tgz", + "integrity": "sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/symbol-tree": { @@ -5227,86 +4024,45 @@ "license": "MIT" }, "node_modules/tailwindcss": { - "version": "3.4.19", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", - "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.7", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.3.3.tgz", + "integrity": "sha512-gOhV3P7ufE62QDGg1zVaTgCR+EtPv92k2nIhVcVKcLmxT1sUBsQGhnZj175j+MqRt4zLF7ic+sCYjfhxMxj7YQ==", "dev": true, "license": "MIT" }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "dev": true, "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "node_modules/tinybench": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-6.1.4.tgz", + "integrity": "sha512-9APumHG7r4yOk4X4WlkmE71aZcv1gvin1czO3OQ1U9iJcFA5Ja/ygyb0vPOVHTthFozUYs8CLoLUlM8grb2lTQ==", "dev": true, "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, "engines": { - "node": ">=0.8" + "node": ">=20.0.0" } }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.3.0.tgz", + "integrity": "sha512-QKAl9m8gWWGHV8jZcPeym6j+XULi6tOf1mT83WYJ4Lk2ytW/uwAWkrP0uFsdoYMdueVJ0qs26wZ+23xeB4ibNQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=18" + } }, "node_modules/tinyglobby": { "version": "0.2.17", @@ -5325,129 +4081,65 @@ "url": "https://github.com/sponsors/SuperchupuDev" } }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz", - "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==", + "node_modules/tldts": { + "version": "7.4.12", + "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.4.12.tgz", + "integrity": "sha512-WylhSDKVeYnWXL3a+vKTaOxjnOeEGw938hImY8zoRWJjRRK/Jp1K+IihBzIONpUmW4e3WmXT6q5FW6vlESVZCA==", "dev": true, "license": "MIT", - "engines": { - "node": ">=12" + "dependencies": { + "tldts-core": "^7.4.12" }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/tinypool": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", - "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/tinyrainbow": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-1.2.0.tgz", - "integrity": "sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" + "bin": { + "tldts": "bin/cli.js" } }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "node_modules/tldts-core": { + "version": "7.4.12", + "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.4.12.tgz", + "integrity": "sha512-nYNzS2WRf4QJmjzFFgAxLOBjyBxAGRbCy9PVBPaglcYyYajh40VBn+v5Ngr96ZMc7oM0+aCJdtQnNejvdBnXMQ==", "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } + "license": "MIT" }, "node_modules/tough-cookie": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", - "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-6.0.2.tgz", + "integrity": "sha512-exgYmnmL/sJpR3upZfXG5PoatXQii55xAiXGXzY+sROLZ/Y+SLcp9PgJNI9Vz37HpQ74WvDcLT8eqm+kV3FzrA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { - "psl": "^1.1.33", - "punycode": "^2.1.1", - "universalify": "^0.2.0", - "url-parse": "^1.5.3" + "tldts": "^7.0.5" }, "engines": { - "node": ">=6" + "node": ">=16" } }, "node_modules/tr46": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz", - "integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-6.0.0.tgz", + "integrity": "sha512-bLVMLPtstlZ4iMQHpFHTR7GAGj2jxi8Dg0s2h2MafAE4uSWF98FC/3MomU51iQAMf8/qDUbKWf5GxuvvVcXEhw==", "dev": true, "license": "MIT", "dependencies": { "punycode": "^2.3.1" }, "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.5.0.tgz", + "integrity": "sha512-OJ/ibxhPlqrMM0UiNHJ/0CKQkoKF243/AEmplt3qpRgkW8VG7IfOS41h7V8TjITqdByHzrjcS/2si+y4lIh8NA==", "dev": true, "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, - "license": "Apache-2.0" - }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", @@ -5462,13 +4154,13 @@ } }, "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -5478,14 +4170,48 @@ "version": "5.9.3", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "dev": true, + "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { - "node": ">=14.17" + "node": ">=14.17" + } + }, + "node_modules/typescript-eslint": { + "version": "8.70.0", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.70.0.tgz", + "integrity": "sha512-P/W5cz70/cQAuKfY3xwQMWWTV7BvJ0mAQmi+9mBcsVPaBUpd6Ohpa+fECv9rBFrQcig86jAiNBFNWUqnTjr4pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/eslint-plugin": "8.70.0", + "@typescript-eslint/parser": "8.70.0", + "@typescript-eslint/typescript-estree": "8.70.0", + "@typescript-eslint/utils": "8.70.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0", + "typescript": ">=4.8.4 <6.1.0" + } + }, + "node_modules/undici": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-8.10.2.tgz", + "integrity": "sha512-/y4/bH9YNU5hi9NIrpOuvGXFcxrj3CMrV+/AYpowAYTpHn8gX/XPFjNy766FPoYY0miQhdW977JFWKGNhBdwyQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=22.19.0" } }, "node_modules/undici-types": { @@ -5494,16 +4220,6 @@ "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", "license": "MIT" }, - "node_modules/universalify": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", - "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4.0.0" - } - }, "node_modules/update-browserslist-db": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.3.tgz", @@ -5538,7 +4254,8 @@ "node_modules/uplot": { "version": "1.6.32", "resolved": "https://registry.npmjs.org/uplot/-/uplot-1.6.32.tgz", - "integrity": "sha512-KIMVnG68zvu5XXUbC4LQEPnhwOxBuLyW1AHtpm6IKTXImkbLgkMy+jabjLgSLMasNuGGzQm/ep3tOkyTxpiQIw==" + "integrity": "sha512-KIMVnG68zvu5XXUbC4LQEPnhwOxBuLyW1AHtpm6IKTXImkbLgkMy+jabjLgSLMasNuGGzQm/ep3tOkyTxpiQIw==", + "license": "MIT" }, "node_modules/uri-js": { "version": "4.4.1", @@ -5557,49 +4274,33 @@ "dev": true, "license": "MIT" }, - "node_modules/url-parse": { - "version": "1.5.10", - "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", - "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "querystringify": "^2.1.1", - "requires-port": "^1.0.0" - } - }, "node_modules/use-sync-external-store": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", - "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.7.0.tgz", + "integrity": "sha512-6L+EeigHMQhdaIPNIFUKwfWJSwWFQ8gJbJ2DLOs5sDIegTwR9fRxvnM3uciHKjIZhFz+KAv2emhWMRvDmMcY8A==", "license": "MIT", "peerDependencies": { "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/vite/-/vite-8.3.0.tgz", + "integrity": "sha512-lhZBVvEHefgE+HQZC9O7EBJgCU/nVzFNl7vkS4RE0APtWLP02/8QVIkQtzBxPquh7lq5/78NHipTj7ODQ6XuyQ==", "dev": true, "license": "MIT", "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" + "lightningcss": "^1.33.0", + "picomatch": "^4.0.7", + "postcss": "^8.5.28", + "rolldown": "~1.2.6", + "tinyglobby": "^0.2.17" }, "bin": { "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^20.19.0 || >=22.12.0" }, "funding": { "url": "https://github.com/vitejs/vite?sponsor=1" @@ -5608,23 +4309,33 @@ "fsevents": "~2.3.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" + "@types/node": "^20.19.0 || >=22.12.0", + "@vitejs/devtools": "^0.7.1", + "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 }, - "less": { + "@vitejs/devtools": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "jiti": { "optional": true }, - "lightningcss": { + "less": { "optional": true }, "sass": { @@ -5641,85 +4352,343 @@ }, "terser": { "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true } } }, - "node_modules/vite-node": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-2.1.9.tgz", - "integrity": "sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==", + "node_modules/vite/node_modules/lightningcss": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.33.0.tgz", + "integrity": "sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==", "dev": true, - "license": "MIT", + "license": "MPL-2.0", "dependencies": { - "cac": "^6.7.14", - "debug": "^4.3.7", - "es-module-lexer": "^1.5.4", - "pathe": "^1.1.2", - "vite": "^5.0.0" + "detect-libc": "^2.0.3" }, - "bin": { - "vite-node": "vite-node.mjs" + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" }, + "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" + } + }, + "node_modules/vite/node_modules/lightningcss-android-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz", + "integrity": "sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": ">= 12.0.0" }, "funding": { - "url": "https://opencollective.com/vitest" + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-darwin-arm64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz", + "integrity": "sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-darwin-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz", + "integrity": "sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-freebsd-x64": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz", + "integrity": "sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz", + "integrity": "sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz", + "integrity": "sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-arm64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz", + "integrity": "sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-x64-gnu": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz", + "integrity": "sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-linux-x64-musl": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz", + "integrity": "sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz", + "integrity": "sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/vite/node_modules/lightningcss-win32-x64-msvc": { + "version": "1.33.0", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz", + "integrity": "sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MPL-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" } }, "node_modules/vitest": { - "version": "2.1.9", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-2.1.9.tgz", - "integrity": "sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "2.1.9", - "@vitest/mocker": "2.1.9", - "@vitest/pretty-format": "^2.1.9", - "@vitest/runner": "2.1.9", - "@vitest/snapshot": "2.1.9", - "@vitest/spy": "2.1.9", - "@vitest/utils": "2.1.9", - "chai": "^5.1.2", - "debug": "^4.3.7", - "expect-type": "^1.1.0", - "magic-string": "^0.30.12", - "pathe": "^1.1.2", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.1", - "tinypool": "^1.0.1", - "tinyrainbow": "^1.2.0", - "vite": "^5.0.0", - "vite-node": "2.1.9", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-5.0.0.tgz", + "integrity": "sha512-gpsMNoRhMjMktVxPtstOH4/PJuPyovVaMDr4oDilXaGH1EcqM2OE96SoHT2VIQ6fTGtTjqmHDrEu2X9RQiXf8Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/mocker": "5.0.0", + "chai": "^6.2.2", + "es-module-lexer": "^2.3.2", + "expect-type": "^1.4.0", + "magic-string": "^1.2.3", + "obug": "^2.1.4", + "picomatch": "^4.0.7", + "std-env": "^4.2.0", + "tinybench": "6.1.4", + "tinyexec": "1.3.0", + "tinyglobby": "^0.2.17", "why-is-node-running": "^2.3.0" }, "bin": { "vitest": "vitest.mjs" }, "engines": { - "node": "^18.0.0 || >=20.0.0" + "node": "^22.12.0 || ^24.0.0 || >=26.0.0" }, "funding": { "url": "https://opencollective.com/vitest" }, "peerDependencies": { "@edge-runtime/vm": "*", - "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "2.1.9", - "@vitest/ui": "2.1.9", + "@opentelemetry/api": "^1.9.0", + "@types/node": "^22.0.0 || >=24.0.0", + "@vitest/browser-playwright": "5.0.0", + "@vitest/browser-preview": "5.0.0", + "@vitest/browser-webdriverio": "^5.0.0-beta.5 || >=5.0.0", + "@vitest/coverage-istanbul": "5.0.0", + "@vitest/coverage-v8": "5.0.0", + "@vitest/ui": "5.0.0", "happy-dom": "*", - "jsdom": "*" + "jsdom": "*", + "vite": "^6.4.0 || ^7.0.0 || ^8.0.0" }, "peerDependenciesMeta": { "@edge-runtime/vm": { "optional": true }, + "@opentelemetry/api": { + "optional": true + }, "@types/node": { "optional": true }, - "@vitest/browser": { + "@vitest/browser-playwright": { + "optional": true + }, + "@vitest/browser-preview": { + "optional": true + }, + "@vitest/browser-webdriverio": { + "optional": true + }, + "@vitest/coverage-istanbul": { + "optional": true + }, + "@vitest/coverage-v8": { "optional": true }, "@vitest/ui": { @@ -5730,16 +4699,20 @@ }, "jsdom": { "optional": true + }, + "vite": { + "optional": false } } }, - "node_modules/void-elements": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", - "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "node_modules/vitest/node_modules/magic-string": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-1.3.1.tgz", + "integrity": "sha512-rm91zr2Ou+XueDTohjQQjdQEcYM6zVi8KVUCG8Ec3vHwUEKrhSdCNyfuIywkA6hcCAteIn0ZOtAHA6eGpiX+Pg==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.6.0" } }, "node_modules/w3c-xmlserializer": { @@ -5756,51 +4729,38 @@ } }, "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-8.0.1.tgz", + "integrity": "sha512-BMhLD/Sw+GbJC21C/UgyaZX41nPt8bUTg+jWyDeg7e7YN4xOM05YPSIXceACnXVtqyEw/LMClUQMtMZ+PGGpqQ==", "dev": true, "license": "BSD-2-Clause", "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-encoding": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", - "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", - "deprecated": "Use @exodus/bytes instead for a more spec-conformant and faster implementation", - "dev": true, - "license": "MIT", - "dependencies": { - "iconv-lite": "0.6.3" - }, - "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/whatwg-mimetype": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", - "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-5.0.0.tgz", + "integrity": "sha512-sXcNcHOC51uPGF0P/D4NVtrkjSU2fNsm9iog4ZvZJsL3rjoDAzXZhkm2MWt1y+PUdggKAYVoMAIYcs78wJ51Cw==", "dev": true, "license": "MIT", "engines": { - "node": ">=18" + "node": ">=20" } }, "node_modules/whatwg-url": { - "version": "14.2.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz", - "integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==", + "version": "17.1.1", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-17.1.1.tgz", + "integrity": "sha512-ohjk1mdUebJVadRt3bAhQhx8lSnISq+GDttK79LFl8EHQkAPvzwctoasC4hs8tBt6kLAncBWWyq1N52qEfKvDw==", "dev": true, "license": "MIT", "dependencies": { - "tr46": "^5.1.0", - "webidl-conversions": "^7.0.0" + "@exodus/bytes": "^1.15.1", + "tr46": "^6.0.0", + "webidl-conversions": "^8.0.1" }, "engines": { - "node": ">=18" + "node": "^22.14.0 || >=24.0.0" } }, "node_modules/which": { @@ -5846,35 +4806,6 @@ "node": ">=0.10.0" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ws": { - "version": "8.21.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.21.0.tgz", - "integrity": "sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/xml-name-validator": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-5.0.0.tgz", @@ -5929,6 +4860,29 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/zod": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.6.2.tgz", + "integrity": "sha512-lh5RCAGFa1Cm2hjtNwLQhSs/AsqdWnTQaBER9fEwN/88pSh7KOtJavtBx/0VlkN/uFd61SwYmljLMDAsHlvzBQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + }, "node_modules/zustand": { "version": "4.5.7", "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", diff --git a/frontend/package.json b/frontend/package.json index 17f86c5..e24edac 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -9,7 +9,7 @@ "build": "tsc -b && vite build", "preview": "vite preview", "gen:api": "openapi-typescript ./openapi.json -o ./src/api/schema.d.ts", - "lint": "eslint . --ext .ts,.tsx", + "lint": "eslint .", "test": "vitest run", "test:watch": "vitest" }, @@ -17,36 +17,40 @@ "@phosphor-icons/react": "^2.1.10", "@tanstack/react-query": "^5.51.0", "@types/papaparse": "^5.5.2", - "i18next": "^23.16.8", - "i18next-browser-languagedetector": "^7.2.2", + "i18next": "^26.4.2", + "i18next-browser-languagedetector": "^8.2.1", "openapi-fetch": "^0.10.5", "papaparse": "^5.6.0", "pretendard": "^1.3.9", "react": "^18.3.1", "react-dom": "^18.3.1", - "react-i18next": "^14.1.3", - "react-router-dom": "^6.30.6", + "react-i18next": "^17.0.13", + "react-router-dom": "^7.18.3", "uplot": "^1.6.32", "zustand": "^4.5.4" }, "devDependencies": { + "@eslint/js": "^10.0.1", + "@tailwindcss/postcss": "^4.3.3", "@testing-library/react": "^16.0.0", - "@types/node": "^20.14.0", + "@types/node": "^22.0.0", "@types/react": "^18.3.3", "@types/react-dom": "^18.3.0", - "@typescript-eslint/eslint-plugin": "^7.18.0", - "@typescript-eslint/parser": "^7.18.0", - "@vitejs/plugin-react": "^4.3.1", - "autoprefixer": "^10.4.19", - "eslint": "^8.57.0", - "eslint-plugin-react-hooks": "^4.6.2", - "eslint-plugin-react-refresh": "^0.4.9", - "jsdom": "^24.1.1", + "@vitejs/plugin-react": "^6.1.1", + "eslint": "^10.10.0", + "eslint-plugin-react-hooks": "^7.1.1", + "eslint-plugin-react-refresh": "^0.5.6", + "globals": "^17.0.0", + "jsdom": "^30.0.1", "openapi-typescript": "^7.3.0", "postcss": "^8.4.40", - "tailwindcss": "^3.4.7", + "tailwindcss": "^4.3.3", "typescript": "^5.5.4", - "vite": "^5.3.5", - "vitest": "^2.0.5" + "typescript-eslint": "^8.70.0", + "vite": "^8.3.0", + "vitest": "^5.0.0" + }, + "engines": { + "node": ">=22.12" } } diff --git a/frontend/postcss.config.js b/frontend/postcss.config.js index 2aa7205..a34a3d5 100644 --- a/frontend/postcss.config.js +++ b/frontend/postcss.config.js @@ -1,6 +1,5 @@ export default { plugins: { - tailwindcss: {}, - autoprefixer: {}, + '@tailwindcss/postcss': {}, }, }; diff --git a/frontend/src/api/hooks/useImages.ts b/frontend/src/api/hooks/useImages.ts index b6d10be..5045281 100644 --- a/frontend/src/api/hooks/useImages.ts +++ b/frontend/src/api/hooks/useImages.ts @@ -27,7 +27,7 @@ const rawImg = api as unknown as { PATCH: (path: string, init?: { body?: unknown; params?: { path?: Record } }) => Promise<{ data?: unknown }>; }; -// GET /images — the catalogue, by registry and tag. +// GET /images — the catalog, by registry and tag. export function useImages(filter: ImageFilter = {}) { return useQuery({ queryKey: imageKeys.list(filter), @@ -52,7 +52,7 @@ export interface ImportImageBody { } // What /images/import answers with. `existing: true` means the reference was already registered — -// by this caller earlier, or in the shared catalogue — and `id` is the row to use as-is. +// by this caller earlier, or in the shared catalog — and `id` is the row to use as-is. export interface ImportedImage { id: string; name: string; diff --git a/frontend/src/api/hooks/useResources.ts b/frontend/src/api/hooks/useResources.ts index fc7580f..3e45152 100644 --- a/frontend/src/api/hooks/useResources.ts +++ b/frontend/src/api/hooks/useResources.ts @@ -1,7 +1,7 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query'; import { api } from '@/api/client'; -// CRUD for the offering catalogue, presets, and resource policies (quotas). +// CRUD for the offering catalog, presets, and resource policies (quotas). // These use the loose accessor so the response envelopes can be typed locally. const raw = api as unknown as { GET: (path: string, init?: { params?: { query?: Record; path?: Record } }) => Promise<{ data?: unknown }>; diff --git a/frontend/src/api/hooks/useSessions.ts b/frontend/src/api/hooks/useSessions.ts index 3b99f0f..71b2616 100644 --- a/frontend/src/api/hooks/useSessions.ts +++ b/frontend/src/api/hooks/useSessions.ts @@ -136,7 +136,7 @@ export function useSessionConnections(id: string, enabled = true) { } // Measured live usage of the caller's own session (owner or admin): cadvisor CPU/MEM plus -// HAMi per-session VRAM and GPU-core utilisation, for the detail page's usage panel. +// HAMi per-session VRAM and GPU-core utilization, for the detail page's usage panel. export interface OwnSessionUsage { cpu_cores: number | null; mem_bytes: number | null; diff --git a/frontend/src/api/hooks/useSystem.ts b/frontend/src/api/hooks/useSystem.ts index 93f6731..673810b 100644 --- a/frontend/src/api/hooks/useSystem.ts +++ b/frontend/src/api/hooks/useSystem.ts @@ -38,7 +38,7 @@ export function cachedBranding(): Branding { function rememberBranding(b: Branding): void { try { localStorage.setItem(CACHE_KEY, JSON.stringify(b)); - } catch { /* nothing to do: the cache is an optimisation, not state */ } + } catch { /* nothing to do: the cache is an optimization, not state */ } } export type SignupMode = 'approval' | 'open' | 'closed'; diff --git a/frontend/src/api/schema.d.ts b/frontend/src/api/schema.d.ts index 47bc4a4..ae6370d 100644 --- a/frontend/src/api/schema.d.ts +++ b/frontend/src/api/schema.d.ts @@ -2134,7 +2134,7 @@ export interface paths { * @description List images/templates/ISOs with optional kind/q/tag/public filters. any authenticated. * * ``public=true`` is what the session wizard uses, listing public images only. The administrative - * catalogue passes no filter and sees both public and private images. + * catalog passes no filter and sees both public and private images. */ get: operations["list_images_api_v1_images_get"]; put?: never; @@ -2158,7 +2158,7 @@ export interface paths { }; /** * Get Image - * @description Image detail. any authenticated, for the shared catalogue and one's own images; another + * @description Image detail. any authenticated, for the shared catalog and one's own images; another * user's private image answers 404 so its existence is not confirmed either. */ get: operations["get_image_api_v1_images__image_id__get"]; @@ -2166,7 +2166,7 @@ export interface paths { post?: never; /** * Delete Image - * @description Delete a catalogue image that no session has ever used. super_admin, gated on image.create. + * @description Delete a catalog image that no session has ever used. super_admin, gated on image.create. * * Sessions keep a foreign key to their image for the audit trail, so an image with any session * history cannot be deleted — retire it instead by setting ``public: false``. @@ -2211,7 +2211,7 @@ export interface paths { * only they and admins can see. The same public ref may therefore be imported by many members. * * Always answers 202. Deduplication never fails the request: re-importing your own ref, or a ref - * that is already in the shared catalogue, returns that row with ``existing: true`` instead of + * that is already in the shared catalog, returns that row with ``existing: true`` instead of * creating a second one — the caller uses the returned ``id`` either way. */ post: operations["import_image_api_v1_images_import_post"]; diff --git a/frontend/src/components/ClusterSelector.tsx b/frontend/src/components/ClusterSelector.tsx index 94ccd03..388291a 100644 --- a/frontend/src/components/ClusterSelector.tsx +++ b/frontend/src/components/ClusterSelector.tsx @@ -42,8 +42,8 @@ export function ClusterSelector() { aria-hidden="true" /> } - buttonClassName={`h-8 pl-2.5 pr-2 rounded-full text-sm font-semibold max-w-[13rem] - border transition-colors duration-150 outline-none + buttonClassName={`h-8 pl-2.5 pr-2 rounded-full text-sm font-semibold max-w-52 + border transition-colors duration-150 outline-hidden focus-visible:ring-2 focus-visible:ring-primary/40 ${narrowed ? 'bg-primary-soft border-primary/35 text-text hover:border-primary/60' diff --git a/frontend/src/components/DetailDrawer.tsx b/frontend/src/components/DetailDrawer.tsx index 0cd0f3c..6737334 100644 --- a/frontend/src/components/DetailDrawer.tsx +++ b/frontend/src/components/DetailDrawer.tsx @@ -39,7 +39,7 @@ export function DetailDrawer({ open, title, tag, onClose, children, footer }: { aria-modal="true" tabIndex={-1} className="absolute inset-y-0 right-0 w-full max-w-[440px] bg-surface border-l border-border - shadow-raised flex flex-col outline-none" + shadow-raised flex flex-col outline-hidden" >

{title}

diff --git a/frontend/src/components/Dialog.tsx b/frontend/src/components/Dialog.tsx index 78a687f..183fdf9 100644 --- a/frontend/src/components/Dialog.tsx +++ b/frontend/src/components/Dialog.tsx @@ -49,7 +49,7 @@ export function Dialog({ open, title, onClose, children, wide }: { aria-modal="true" tabIndex={-1} className={`relative w-full ${wide ? 'max-w-2xl' : 'max-w-lg'} max-h-[85vh] flex flex-col - bg-surface border border-border rounded-card shadow-raised outline-none`} + bg-surface border border-border rounded-card shadow-raised outline-hidden`} >

{title}

diff --git a/frontend/src/components/EmptyState.tsx b/frontend/src/components/EmptyState.tsx index 72295d4..53282e4 100644 --- a/frontend/src/components/EmptyState.tsx +++ b/frontend/src/components/EmptyState.tsx @@ -65,7 +65,7 @@ export function TableSkeleton({ rows = 5, columns = 4 }: { rows?: number; column {Array.from({ length: rows }).map((_, r) => (
{Array.from({ length: columns }).map((__, c) => ( -
+
))}
))} diff --git a/frontend/src/components/Field.tsx b/frontend/src/components/Field.tsx index 5e66402..f03990d 100644 --- a/frontend/src/components/Field.tsx +++ b/frontend/src/components/Field.tsx @@ -2,7 +2,7 @@ import { useId, type ReactNode } from 'react'; import { useTranslation } from 'react-i18next'; /** - * One labelled form control: `