diff --git a/.github/workflows/python-test.yml b/.github/workflows/python-test.yml index f6959960..7ee8038a 100644 --- a/.github/workflows/python-test.yml +++ b/.github/workflows/python-test.yml @@ -61,7 +61,7 @@ jobs: - name: Install Node.js packages run: npm ci - working-directory: web-app + working-directory: web - name: Install Python packages run: uv sync --all-packages diff --git a/.github/workflows/typescript-lint.yml b/.github/workflows/typescript-lint.yml index e8e8c083..5ac21569 100644 --- a/.github/workflows/typescript-lint.yml +++ b/.github/workflows/typescript-lint.yml @@ -7,7 +7,7 @@ on: - production paths: - .github/workflows/typescript-lint.yml - - web-app/** + - web/** - Makefile pull_request: branches: @@ -15,7 +15,7 @@ on: - production paths: - .github/workflows/typescript-lint.yml - - web-app/** + - web/** - Makefile jobs: @@ -23,7 +23,7 @@ jobs: runs-on: ubuntu-latest defaults: run: - working-directory: web-app + working-directory: web steps: - uses: actions/checkout@v6 diff --git a/.github/workflows/typescript-test.yml b/.github/workflows/typescript-test.yml index 4a77908e..ee968962 100644 --- a/.github/workflows/typescript-test.yml +++ b/.github/workflows/typescript-test.yml @@ -7,7 +7,7 @@ on: - production paths: - .github/workflows/typescript-test.yml - - web-app/** + - web/** - Makefile pull_request: branches: @@ -15,7 +15,7 @@ on: - production paths: - .github/workflows/typescript-test.yml - - web-app/** + - web/** - Makefile jobs: @@ -51,7 +51,7 @@ jobs: - name: Install packages run: npm ci - working-directory: web-app + working-directory: web - name: Run MCP tests run: make fe-test-mcp diff --git a/Makefile b/Makefile index 86b31aba..72579039 100644 --- a/Makefile +++ b/Makefile @@ -49,35 +49,35 @@ py-check-watcher-version: # Web app. .PHONY: fe-format fe-format: - cd web-app && npm run format + cd web && npm run format .PHONY: fe-lint fe-lint: - cd web-app && npm run lint + cd web && npm run lint .PHONY: fe-typecheck fe-typecheck: - cd web-app && npm run typecheck + cd web && npm run typecheck .PHONY: fe-test-mcp fe-test-mcp: - cd web-app && npm run test:mcp + cd web && npm run test:mcp .PHONY: fe-test-integration fe-test-integration: - cd web-app && npm run test:integration + cd web && npm run test:integration .PHONY: fe-test fe-test: - cd web-app && npm run test:mcp && npm run test:integration + cd web && npm run test:mcp && npm run test:integration .PHONY: dev dev: - cd web-app && npm run dev + cd web && npm run dev .PHONY: fe-build fe-build: - cd web-app && npm run build + cd web && npm run build # Formatting, linting, and type checking. .PHONY: py-check diff --git a/README.md b/README.md index a86ec32c..d46430c0 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ flowchart LR | Directory | Description | Docs | | --- | --- | --- | -| `web-app/` | Next.js web application and REST API (Vercel) | [API reference](docs/api.md) | +| `web/` | Next.js web application and REST API (Vercel) | [API reference](docs/api.md) | | `lambda/` | AWS Lambda function for instrument data processing | [Lambda docs](docs/lambda.md) | | `watcher/` | CLI agent for lab instrument PCs | [Watcher docs](docs/watcher.md) | | `packages/shared/` | Shared Python library (S3, enums, test infra) | [Shared library](docs/shared-library.md) | @@ -29,13 +29,13 @@ flowchart LR uv sync --all-packages # Install web app dependencies. -cd web-app && npm install && cd .. +cd web && npm install && cd .. # Set up environment variables for the web app. -cd web-app && vercel env pull && cd .. +cd web && vercel env pull && cd .. # Create and initialize the local database. -cd web-app && createdb data-hub-local && npm run db:push && cd .. +cd web && createdb data-hub-local && npm run db:push && cd .. # Start the dev server. make dev diff --git a/docs/architecture.md b/docs/architecture.md index 0672f0c2..7648dbff 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -24,7 +24,7 @@ flowchart LR | Directory | Package | Description | | --- | --- | --- | -| `web-app/` | `data-hub-web-app` | Next.js web application, REST API, and MCP server. Deployed on Vercel. | +| `web/` | `data-hub-web` | Next.js web application, REST API, and MCP server. Deployed on Vercel. | | `lambda/` | `data-hub-lambda` | AWS Lambda function triggered by S3 uploads. Runs instrument-specific processing pipelines. | | `watcher/` | `data-hub-watcher` | CLI agent installed on lab instrument PCs. Detects new files, uploads them to S3, and reports status to the API. | | `packages/shared/` | `data-hub-shared` | Shared Python library providing S3 utilities, instrument enums, and test infrastructure. | @@ -56,7 +56,7 @@ Steps 1–3 are the same, but the watcher does not upload immediately. Instead: - **API-driven coordination.** The watcher registers with the API, syncs its YAML config, and sends periodic heartbeats. This lets the web dashboard show watcher health and manage upload queues. - **Presigned URLs from the API.** The web app generates presigned S3 upload and download URLs so watchers and browsers can transfer files directly to/from S3 without routing data through the API. On Vercel, the app assumes an IAM role via OIDC federation (no long-lived AWS credentials). - **Lambda-built run archives.** The "Download all" actions on a run delegate to the Lambda, which streams files from the raw + processed buckets directly into a zip in a separate `arcadia-data-hub-archives-{env}` bucket via S3 multipart upload. The web app then 302s the browser to a short-lived presigned URL on that archive — bytes never traverse Vercel, eliminating Fast Origin Transfer for run downloads. Builds are cached at `runs/{instrument_id}/{run_id}/{fingerprint}.zip` and expire after 7 days. Every cache miss is dispatched asynchronously: the route inserts an `archive_jobs` row, schedules the Lambda invocation via `after()`, returns `202 { job_id }`, and the UI polls the same `/download-archive` URL (which HEADs S3 on each call) until the artifact appears — making the S3 object, not the row's `status`, the source of truth for "ready". See [Run archives](run-archives.md) for the full flow and runbook. -- **Public page metadata, gated bodies.** Routes commonly shared into Slack/Notion (dashboard, instruments, instrument and run detail, settings) are reachable without a session so link unfurlers can read `` metadata; the page or layout renders a `SignInRequired` CTA in place of the real body when there's no session. `/watchers/*` stays redirected to `/login` by `web-app/proxy.ts`. Three independent layers prevent search indexing: a `robots` field on the root layout, an `app/robots.ts` that disallows all generic crawlers (with an allow-list for unfurl bots), and an `X-Robots-Tag: noindex, nofollow` header on every response. +- **Public page metadata, gated bodies.** Routes commonly shared into Slack/Notion (dashboard, instruments, instrument and run detail, settings) are reachable without a session so link unfurlers can read `` metadata; the page or layout renders a `SignInRequired` CTA in place of the real body when there's no session. `/watchers/*` stays redirected to `/login` by `web/proxy.ts`. Three independent layers prevent search indexing: a `robots` field on the root layout, an `app/robots.ts` that disallows all generic crawlers (with an allow-list for unfurl bots), and an `X-Robots-Tag: noindex, nofollow` header on every response. - **Shared library for contracts.** Instrument IDs, S3 utilities, and environment config live in `data-hub-shared` so they stay consistent across Lambda and the watcher without duplicating code. - **MCP for AI access.** The web app includes a [Model Context Protocol](https://modelcontextprotocol.io/) server at `/api/v1/mcp` that exposes read-only tools, resources, and prompts. AI clients (e.g. Claude Desktop, Cursor) can query instruments, runs, and system status using a personal access token. - **Integration tests against a real server.** The shared `testing.py` module spins up a real Next.js server backed by a Postgres database, so Lambda and watcher integration tests exercise the actual API surface. diff --git a/docs/ci-and-deployment.md b/docs/ci-and-deployment.md index 51b4d7c3..6b627718 100644 --- a/docs/ci-and-deployment.md +++ b/docs/ci-and-deployment.md @@ -57,7 +57,7 @@ The Next.js app is deployed on [Vercel](https://vercel.com/arcadia-science/data- Environment variables are managed in the Vercel dashboard and can be pulled locally with: ```sh -cd web-app +cd web vercel env pull ``` @@ -68,7 +68,7 @@ Staging and production each have a dedicated PostgreSQL instance hosted on [Rend Schema changes are applied with Drizzle: ```sh -cd web-app +cd web # Generate migration files from schema changes. npm run db:generate @@ -168,7 +168,7 @@ In your GitHub repo, go to **Settings → Environments**, create a `staging` env | `DATA_HUB_API_URL` | Base API URL for the environment | | `DATA_HUB_API_KEY` | API key for Lambda → Data Hub authentication (also used by the Lambda's archive-job PATCH callback) | -Slack notifications are sent by the **web app** (not the Lambda) when a new run is created. Configure `SLACK_WEBHOOK_URL` per environment in the Vercel dashboard alongside the other web-app env vars listed below. +Slack notifications are sent by the **web app** (not the Lambda) when a new run is created. Configure `SLACK_WEBHOOK_URL` per environment in the Vercel dashboard alongside the other web app env vars listed below. You'll also need the `WebAppRoleArn` and `DataHubFunctionUrl` stack outputs to configure the Vercel web app. In the Vercel dashboard (under the appropriate environment), set: diff --git a/docs/getting-started.md b/docs/getting-started.md index cf47925a..8712e194 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -23,7 +23,7 @@ cd data-hub uv sync --all-packages # Install web app dependencies. -cd web-app && npm install && cd .. +cd web && npm install && cd .. ``` The Python workspace is managed by uv. The root `pyproject.toml` defines three workspace members — `lambda`, `watcher`, and `packages/shared` — and all are installed together by `uv sync --all-packages`. @@ -35,7 +35,7 @@ The Python workspace is managed by uv. The root `pyproject.toml` defines three w The web app requires the following variables. The easiest way to get them is via the Vercel CLI: ```sh -cd web-app +cd web vercel env pull ``` @@ -72,7 +72,7 @@ The watcher reads its configuration from a YAML file at `~/.data-hub/config.yaml ## Database setup ```sh -cd web-app +cd web # Create a local PostgreSQL database. createdb data-hub-local @@ -98,7 +98,7 @@ Other database commands: make dev # Or equivalently: -cd web-app && npm run dev +cd web && npm run dev ``` The app runs at [http://localhost:3000](http://localhost:3000). diff --git a/docs/lambda.md b/docs/lambda.md index 86e99070..f2a5ea1b 100644 --- a/docs/lambda.md +++ b/docs/lambda.md @@ -54,7 +54,7 @@ Each processor module exposes a `process_file()` function that accepts the run I ## Slack notifications -Slack notifications are sent by the **web app** (`web-app/lib/slack.ts`), not the Lambda. When the Lambda's `process_file` calls `POST /api/v1/instruments/:instrumentId/runs` to register a newly-detected run, that endpoint posts a single message per run to `SLACK_WEBHOOK_URL` (configured per environment in Vercel). Subsequent files for the same run do not re-notify because the upsert is idempotent on `(instrument_id, run_id)`. File-level failures remain visible in the web app via the file row's `status='failed'` and `error_message` fields. +Slack notifications are sent by the **web app** (`web/lib/slack.ts`), not the Lambda. When the Lambda's `process_file` calls `POST /api/v1/instruments/:instrumentId/runs` to register a newly-detected run, that endpoint posts a single message per run to `SLACK_WEBHOOK_URL` (configured per environment in Vercel). Subsequent files for the same run do not re-notify because the upsert is idempotent on `(instrument_id, run_id)`. File-level failures remain visible in the web app via the file row's `status='failed'` and `error_message` fields. ## Adding a new instrument diff --git a/docs/run-archives.md b/docs/run-archives.md index 99960e92..8a92a6c8 100644 --- a/docs/run-archives.md +++ b/docs/run-archives.md @@ -45,7 +45,7 @@ Archives live in a separate bucket per environment, provisioned by [`infra/templ The fingerprint is a sorted SHA-256 of `(file_id, s3_key)` pairs: ```ts -// web-app/lib/api/archive-builder.ts +// web/lib/api/archive-builder.ts [...files].map((f) => `${f.id}:${f.s3Key}`).sort().join("|") ``` @@ -61,7 +61,7 @@ Properties this gives us: Two simultaneous "Download all" clicks must not double-invoke the Lambda. The schema enforces this with a *partial* unique index: ```sql --- web-app/drizzle/0016_add_archive_jobs.sql +-- web/drizzle/0016_add_archive_jobs.sql CREATE UNIQUE INDEX archive_jobs_inflight_unique_idx ON archive_jobs (instrument_run_id, fingerprint) WHERE status IN ('pending', 'building'); diff --git a/lambda/src/data_hub_lambda/handler.py b/lambda/src/data_hub_lambda/handler.py index 2e0f6a0d..72e9cfa7 100644 --- a/lambda/src/data_hub_lambda/handler.py +++ b/lambda/src/data_hub_lambda/handler.py @@ -151,7 +151,7 @@ def _handle_build_archive(payload: dict[str, Any]) -> dict[str, Any]: """Run the archive builder and (optionally) PATCH the originating job. Sync callers (``payload["job_id"]`` absent) get the build result inline. - Async callers send ``"job_id"`` so the web-app job row gets PATCHed when + Async callers send ``"job_id"`` so the web app job row gets PATCHed when the build finishes — the HTTP response is the ack of acceptance and the actual outcome is delivered out-of-band. """ @@ -246,7 +246,7 @@ def _post_archive_job_status( Failures here are logged but never re-raised — the build itself succeeded or failed for its own reasons, and we don't want a callback failure to - mask that. The web-app's UI does not depend on this PATCH landing + mask that. The web app's UI does not depend on this PATCH landing either: it polls ``/download-archive`` which short-circuits on an S3 HEAD, so a finished build is downloadable the moment the multipart upload completes. diff --git a/packages/shared/src/data_hub_shared/testing.py b/packages/shared/src/data_hub_shared/testing.py index 94f50adb..10703d88 100644 --- a/packages/shared/src/data_hub_shared/testing.py +++ b/packages/shared/src/data_hub_shared/testing.py @@ -39,7 +39,7 @@ _TOKEN_PREFIX = "dhub_" # testing.py lives at packages/shared/src/data_hub_shared/ — walk up 4 levels to the repo root. -_WEB_APP_DIR = Path(__file__).resolve().parents[4] / "web-app" +_WEB_DIR = Path(__file__).resolve().parents[4] / "web" # --------------------------------------------------------------------------- @@ -115,7 +115,7 @@ def wait_for_server( # --------------------------------------------------------------------------- -# Token helpers — must match web-app/lib/tokens.ts +# Token helpers — must match web/lib/tokens.ts # --------------------------------------------------------------------------- @@ -230,7 +230,7 @@ def start_test_server() -> Generator[IntegrationEnv, None, None]: # 2. Push the Drizzle schema. subprocess.run( ["npx", "drizzle-kit", "push", "--force"], - cwd=str(_WEB_APP_DIR), + cwd=str(_WEB_DIR), env={**os.environ, "DATABASE_URL": _DATABASE_URL}, check=True, capture_output=True, @@ -260,7 +260,7 @@ def start_test_server() -> Generator[IntegrationEnv, None, None]: build_result = subprocess.run( ["npx", "next", "build"], - cwd=str(_WEB_APP_DIR), + cwd=str(_WEB_DIR), env=server_env, capture_output=True, ) @@ -273,7 +273,7 @@ def start_test_server() -> Generator[IntegrationEnv, None, None]: server_proc = subprocess.Popen( ["npx", "next", "start", "-p", str(port)], - cwd=str(_WEB_APP_DIR), + cwd=str(_WEB_DIR), env=server_env, stdout=subprocess.PIPE, stderr=subprocess.PIPE, diff --git a/watcher/tests/integration/test_update_check.py b/watcher/tests/integration/test_update_check.py index 7b498d84..5a74396b 100644 --- a/watcher/tests/integration/test_update_check.py +++ b/watcher/tests/integration/test_update_check.py @@ -1,6 +1,6 @@ """Integration tests: watcher update-check endpoint via DataHubClient. -The TS-side tests in `web-app/tests/integration/watchers.test.ts` cover +The TS-side tests in `web/tests/integration/watchers.test.ts` cover the HTTP shape; this file ensures the Python `DataHubClient` plumbing parses the response into the typed `WatcherUpdateInfoResponse` model correctly so the CLI / in-process updater can consume it. diff --git a/web-app/.env.example b/web/.env.example similarity index 100% rename from web-app/.env.example rename to web/.env.example diff --git a/web-app/.gitignore b/web/.gitignore similarity index 100% rename from web-app/.gitignore rename to web/.gitignore diff --git a/web-app/.prettierignore b/web/.prettierignore similarity index 100% rename from web-app/.prettierignore rename to web/.prettierignore diff --git a/web-app/.prettierrc b/web/.prettierrc similarity index 100% rename from web-app/.prettierrc rename to web/.prettierrc diff --git a/web-app/README.md b/web/README.md similarity index 100% rename from web-app/README.md rename to web/README.md diff --git a/web-app/app/api/auth/[...nextauth]/route.ts b/web/app/api/auth/[...nextauth]/route.ts similarity index 100% rename from web-app/app/api/auth/[...nextauth]/route.ts rename to web/app/api/auth/[...nextauth]/route.ts diff --git a/web-app/app/api/v1/archive-jobs/[id]/route.ts b/web/app/api/v1/archive-jobs/[id]/route.ts similarity index 100% rename from web-app/app/api/v1/archive-jobs/[id]/route.ts rename to web/app/api/v1/archive-jobs/[id]/route.ts diff --git a/web-app/app/api/v1/files/[fileId]/download/route.ts b/web/app/api/v1/files/[fileId]/download/route.ts similarity index 100% rename from web-app/app/api/v1/files/[fileId]/download/route.ts rename to web/app/api/v1/files/[fileId]/download/route.ts diff --git a/web-app/app/api/v1/files/[fileId]/reprocess/route.ts b/web/app/api/v1/files/[fileId]/reprocess/route.ts similarity index 100% rename from web-app/app/api/v1/files/[fileId]/reprocess/route.ts rename to web/app/api/v1/files/[fileId]/reprocess/route.ts diff --git a/web-app/app/api/v1/files/[fileId]/route.ts b/web/app/api/v1/files/[fileId]/route.ts similarity index 100% rename from web-app/app/api/v1/files/[fileId]/route.ts rename to web/app/api/v1/files/[fileId]/route.ts diff --git a/web-app/app/api/v1/instrument-runs/route.ts b/web/app/api/v1/instrument-runs/route.ts similarity index 100% rename from web-app/app/api/v1/instrument-runs/route.ts rename to web/app/api/v1/instrument-runs/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/route.ts b/web/app/api/v1/instruments/[instrumentId]/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/route.ts rename to web/app/api/v1/instruments/[instrumentId]/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/attributions/me/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/attributions/me/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/attributions/me/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/attributions/me/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/[commentId]/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/[commentId]/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/[commentId]/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/[commentId]/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/comments/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/download-archive/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/download-archive/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/download-archive/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/download-archive/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/files/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/files/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/files/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/files/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/reprocess/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/reprocess/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/reprocess/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/reprocess/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-all/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-all/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-all/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-all/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-url/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-url/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-url/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload-url/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/request-upload/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/restore/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/restore/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/restore/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/restore/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/[runId]/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/[runId]/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/[runId]/route.ts diff --git a/web-app/app/api/v1/instruments/[instrumentId]/runs/route.ts b/web/app/api/v1/instruments/[instrumentId]/runs/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/[instrumentId]/runs/route.ts rename to web/app/api/v1/instruments/[instrumentId]/runs/route.ts diff --git a/web-app/app/api/v1/instruments/route.ts b/web/app/api/v1/instruments/route.ts similarity index 100% rename from web-app/app/api/v1/instruments/route.ts rename to web/app/api/v1/instruments/route.ts diff --git a/web-app/app/api/v1/mcp/route.ts b/web/app/api/v1/mcp/route.ts similarity index 100% rename from web-app/app/api/v1/mcp/route.ts rename to web/app/api/v1/mcp/route.ts diff --git a/web-app/app/api/v1/tokens/[id]/route.ts b/web/app/api/v1/tokens/[id]/route.ts similarity index 100% rename from web-app/app/api/v1/tokens/[id]/route.ts rename to web/app/api/v1/tokens/[id]/route.ts diff --git a/web-app/app/api/v1/tokens/route.ts b/web/app/api/v1/tokens/route.ts similarity index 100% rename from web-app/app/api/v1/tokens/route.ts rename to web/app/api/v1/tokens/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/config-checksum/route.ts b/web/app/api/v1/watchers/[watcherId]/config-checksum/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/config-checksum/route.ts rename to web/app/api/v1/watchers/[watcherId]/config-checksum/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/config/route.ts b/web/app/api/v1/watchers/[watcherId]/config/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/config/route.ts rename to web/app/api/v1/watchers/[watcherId]/config/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/events/route.ts b/web/app/api/v1/watchers/[watcherId]/events/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/events/route.ts rename to web/app/api/v1/watchers/[watcherId]/events/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/heartbeat/route.ts b/web/app/api/v1/watchers/[watcherId]/heartbeat/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/heartbeat/route.ts rename to web/app/api/v1/watchers/[watcherId]/heartbeat/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/heartbeats/route.ts b/web/app/api/v1/watchers/[watcherId]/heartbeats/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/heartbeats/route.ts rename to web/app/api/v1/watchers/[watcherId]/heartbeats/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/route.ts b/web/app/api/v1/watchers/[watcherId]/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/route.ts rename to web/app/api/v1/watchers/[watcherId]/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/update-check/route.ts b/web/app/api/v1/watchers/[watcherId]/update-check/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/update-check/route.ts rename to web/app/api/v1/watchers/[watcherId]/update-check/route.ts diff --git a/web-app/app/api/v1/watchers/[watcherId]/upload-queue/route.ts b/web/app/api/v1/watchers/[watcherId]/upload-queue/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/[watcherId]/upload-queue/route.ts rename to web/app/api/v1/watchers/[watcherId]/upload-queue/route.ts diff --git a/web-app/app/api/v1/watchers/register/route.ts b/web/app/api/v1/watchers/register/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/register/route.ts rename to web/app/api/v1/watchers/register/route.ts diff --git a/web-app/app/api/v1/watchers/route.ts b/web/app/api/v1/watchers/route.ts similarity index 100% rename from web-app/app/api/v1/watchers/route.ts rename to web/app/api/v1/watchers/route.ts diff --git a/web-app/app/globals.css b/web/app/globals.css similarity index 100% rename from web-app/app/globals.css rename to web/app/globals.css diff --git a/web-app/app/icon.svg b/web/app/icon.svg similarity index 100% rename from web-app/app/icon.svg rename to web/app/icon.svg diff --git a/web-app/app/instruments/[instrumentId]/page.tsx b/web/app/instruments/[instrumentId]/page.tsx similarity index 100% rename from web-app/app/instruments/[instrumentId]/page.tsx rename to web/app/instruments/[instrumentId]/page.tsx diff --git a/web-app/app/instruments/[instrumentId]/runs/[runId]/page.tsx b/web/app/instruments/[instrumentId]/runs/[runId]/page.tsx similarity index 100% rename from web-app/app/instruments/[instrumentId]/runs/[runId]/page.tsx rename to web/app/instruments/[instrumentId]/runs/[runId]/page.tsx diff --git a/web-app/app/instruments/page.tsx b/web/app/instruments/page.tsx similarity index 100% rename from web-app/app/instruments/page.tsx rename to web/app/instruments/page.tsx diff --git a/web-app/app/layout.tsx b/web/app/layout.tsx similarity index 100% rename from web-app/app/layout.tsx rename to web/app/layout.tsx diff --git a/web-app/app/login/page.tsx b/web/app/login/page.tsx similarity index 100% rename from web-app/app/login/page.tsx rename to web/app/login/page.tsx diff --git a/web-app/app/page.tsx b/web/app/page.tsx similarity index 100% rename from web-app/app/page.tsx rename to web/app/page.tsx diff --git a/web-app/app/robots.ts b/web/app/robots.ts similarity index 100% rename from web-app/app/robots.ts rename to web/app/robots.ts diff --git a/web-app/app/settings/layout.tsx b/web/app/settings/layout.tsx similarity index 100% rename from web-app/app/settings/layout.tsx rename to web/app/settings/layout.tsx diff --git a/web-app/app/settings/page.tsx b/web/app/settings/page.tsx similarity index 100% rename from web-app/app/settings/page.tsx rename to web/app/settings/page.tsx diff --git a/web-app/app/settings/tokens/page.tsx b/web/app/settings/tokens/page.tsx similarity index 100% rename from web-app/app/settings/tokens/page.tsx rename to web/app/settings/tokens/page.tsx diff --git a/web-app/app/watchers/[watcherId]/page.tsx b/web/app/watchers/[watcherId]/page.tsx similarity index 100% rename from web-app/app/watchers/[watcherId]/page.tsx rename to web/app/watchers/[watcherId]/page.tsx diff --git a/web-app/app/watchers/page.tsx b/web/app/watchers/page.tsx similarity index 100% rename from web-app/app/watchers/page.tsx rename to web/app/watchers/page.tsx diff --git a/web-app/components.json b/web/components.json similarity index 100% rename from web-app/components.json rename to web/components.json diff --git a/web-app/components/app-sidebar/app-sidebar-content.tsx b/web/components/app-sidebar/app-sidebar-content.tsx similarity index 100% rename from web-app/components/app-sidebar/app-sidebar-content.tsx rename to web/components/app-sidebar/app-sidebar-content.tsx diff --git a/web-app/components/app-sidebar/index.tsx b/web/components/app-sidebar/index.tsx similarity index 100% rename from web-app/components/app-sidebar/index.tsx rename to web/components/app-sidebar/index.tsx diff --git a/web-app/components/app-sidebar/main-nav.tsx b/web/components/app-sidebar/main-nav.tsx similarity index 100% rename from web-app/components/app-sidebar/main-nav.tsx rename to web/components/app-sidebar/main-nav.tsx diff --git a/web-app/components/app-sidebar/settings-nav.tsx b/web/components/app-sidebar/settings-nav.tsx similarity index 100% rename from web-app/components/app-sidebar/settings-nav.tsx rename to web/components/app-sidebar/settings-nav.tsx diff --git a/web-app/components/app-sidebar/user-menu-footer.tsx b/web/components/app-sidebar/user-menu-footer.tsx similarity index 100% rename from web-app/components/app-sidebar/user-menu-footer.tsx rename to web/components/app-sidebar/user-menu-footer.tsx diff --git a/web-app/components/auth/sign-in-required.tsx b/web/components/auth/sign-in-required.tsx similarity index 100% rename from web-app/components/auth/sign-in-required.tsx rename to web/components/auth/sign-in-required.tsx diff --git a/web-app/components/code-block.tsx b/web/components/code-block.tsx similarity index 100% rename from web-app/components/code-block.tsx rename to web/components/code-block.tsx diff --git a/web-app/components/copy-button.tsx b/web/components/copy-button.tsx similarity index 100% rename from web-app/components/copy-button.tsx rename to web/components/copy-button.tsx diff --git a/web-app/components/dashboard/dashboard-stats.tsx b/web/components/dashboard/dashboard-stats.tsx similarity index 100% rename from web-app/components/dashboard/dashboard-stats.tsx rename to web/components/dashboard/dashboard-stats.tsx diff --git a/web-app/components/dashboard/relative-time.tsx b/web/components/dashboard/relative-time.tsx similarity index 100% rename from web-app/components/dashboard/relative-time.tsx rename to web/components/dashboard/relative-time.tsx diff --git a/web-app/components/dashboard/runs-table.tsx b/web/components/dashboard/runs-table.tsx similarity index 100% rename from web-app/components/dashboard/runs-table.tsx rename to web/components/dashboard/runs-table.tsx diff --git a/web-app/components/dashboard/runs-toolbar.tsx b/web/components/dashboard/runs-toolbar.tsx similarity index 100% rename from web-app/components/dashboard/runs-toolbar.tsx rename to web/components/dashboard/runs-toolbar.tsx diff --git a/web-app/components/instruments/edit-instrument-dialog.tsx b/web/components/instruments/edit-instrument-dialog.tsx similarity index 100% rename from web-app/components/instruments/edit-instrument-dialog.tsx rename to web/components/instruments/edit-instrument-dialog.tsx diff --git a/web-app/components/instruments/instrument-header.tsx b/web/components/instruments/instrument-header.tsx similarity index 100% rename from web-app/components/instruments/instrument-header.tsx rename to web/components/instruments/instrument-header.tsx diff --git a/web-app/components/instruments/instrument-runs-toolbar.tsx b/web/components/instruments/instrument-runs-toolbar.tsx similarity index 100% rename from web-app/components/instruments/instrument-runs-toolbar.tsx rename to web/components/instruments/instrument-runs-toolbar.tsx diff --git a/web-app/components/instruments/instruments-table.tsx b/web/components/instruments/instruments-table.tsx similarity index 100% rename from web-app/components/instruments/instruments-table.tsx rename to web/components/instruments/instruments-table.tsx diff --git a/web-app/components/instruments/row-actions-cell.tsx b/web/components/instruments/row-actions-cell.tsx similarity index 100% rename from web-app/components/instruments/row-actions-cell.tsx rename to web/components/instruments/row-actions-cell.tsx diff --git a/web-app/components/instruments/runs-table/acquired-column-header.tsx b/web/components/instruments/runs-table/acquired-column-header.tsx similarity index 100% rename from web-app/components/instruments/runs-table/acquired-column-header.tsx rename to web/components/instruments/runs-table/acquired-column-header.tsx diff --git a/web-app/components/instruments/runs-table/clickable-row.tsx b/web/components/instruments/runs-table/clickable-row.tsx similarity index 100% rename from web-app/components/instruments/runs-table/clickable-row.tsx rename to web/components/instruments/runs-table/clickable-row.tsx diff --git a/web-app/components/instruments/runs-table/default-runs-table.tsx b/web/components/instruments/runs-table/default-runs-table.tsx similarity index 100% rename from web-app/components/instruments/runs-table/default-runs-table.tsx rename to web/components/instruments/runs-table/default-runs-table.tsx diff --git a/web-app/components/instruments/runs-table/epson-scanner-runs-table.tsx b/web/components/instruments/runs-table/epson-scanner-runs-table.tsx similarity index 100% rename from web-app/components/instruments/runs-table/epson-scanner-runs-table.tsx rename to web/components/instruments/runs-table/epson-scanner-runs-table.tsx diff --git a/web-app/components/instruments/runs-table/filterable-column-header.tsx b/web/components/instruments/runs-table/filterable-column-header.tsx similarity index 100% rename from web-app/components/instruments/runs-table/filterable-column-header.tsx rename to web/components/instruments/runs-table/filterable-column-header.tsx diff --git a/web-app/components/instruments/runs-table/gel-doc-runs-table.tsx b/web/components/instruments/runs-table/gel-doc-runs-table.tsx similarity index 100% rename from web-app/components/instruments/runs-table/gel-doc-runs-table.tsx rename to web/components/instruments/runs-table/gel-doc-runs-table.tsx diff --git a/web-app/components/instruments/runs-table/hina-runs-table.tsx b/web/components/instruments/runs-table/hina-runs-table.tsx similarity index 100% rename from web-app/components/instruments/runs-table/hina-runs-table.tsx rename to web/components/instruments/runs-table/hina-runs-table.tsx diff --git a/web-app/components/instruments/runs-table/index.tsx b/web/components/instruments/runs-table/index.tsx similarity index 100% rename from web-app/components/instruments/runs-table/index.tsx rename to web/components/instruments/runs-table/index.tsx diff --git a/web-app/components/instruments/runs-table/metadata-utils.tsx b/web/components/instruments/runs-table/metadata-utils.tsx similarity index 100% rename from web-app/components/instruments/runs-table/metadata-utils.tsx rename to web/components/instruments/runs-table/metadata-utils.tsx diff --git a/web-app/components/instruments/runs-table/plate-reader-runs-table.tsx b/web/components/instruments/runs-table/plate-reader-runs-table.tsx similarity index 100% rename from web-app/components/instruments/runs-table/plate-reader-runs-table.tsx rename to web/components/instruments/runs-table/plate-reader-runs-table.tsx diff --git a/web-app/components/instruments/runs-table/qpcr-runs-table.tsx b/web/components/instruments/runs-table/qpcr-runs-table.tsx similarity index 100% rename from web-app/components/instruments/runs-table/qpcr-runs-table.tsx rename to web/components/instruments/runs-table/qpcr-runs-table.tsx diff --git a/web-app/components/instruments/runs-table/ran-by-cell.tsx b/web/components/instruments/runs-table/ran-by-cell.tsx similarity index 100% rename from web-app/components/instruments/runs-table/ran-by-cell.tsx rename to web/components/instruments/runs-table/ran-by-cell.tsx diff --git a/web-app/components/instruments/runs-table/raw-file-column-header.tsx b/web/components/instruments/runs-table/raw-file-column-header.tsx similarity index 100% rename from web-app/components/instruments/runs-table/raw-file-column-header.tsx rename to web/components/instruments/runs-table/raw-file-column-header.tsx diff --git a/web-app/components/instruments/runs-table/run-bulk-action-bar.tsx b/web/components/instruments/runs-table/run-bulk-action-bar.tsx similarity index 100% rename from web-app/components/instruments/runs-table/run-bulk-action-bar.tsx rename to web/components/instruments/runs-table/run-bulk-action-bar.tsx diff --git a/web-app/components/instruments/runs-table/run-id-label.tsx b/web/components/instruments/runs-table/run-id-label.tsx similarity index 100% rename from web-app/components/instruments/runs-table/run-id-label.tsx rename to web/components/instruments/runs-table/run-id-label.tsx diff --git a/web-app/components/instruments/runs-table/run-row-actions.tsx b/web/components/instruments/runs-table/run-row-actions.tsx similarity index 100% rename from web-app/components/instruments/runs-table/run-row-actions.tsx rename to web/components/instruments/runs-table/run-row-actions.tsx diff --git a/web-app/components/instruments/runs-table/run-select-checkbox.tsx b/web/components/instruments/runs-table/run-select-checkbox.tsx similarity index 100% rename from web-app/components/instruments/runs-table/run-select-checkbox.tsx rename to web/components/instruments/runs-table/run-select-checkbox.tsx diff --git a/web-app/components/instruments/runs-table/run-selection-provider.tsx b/web/components/instruments/runs-table/run-selection-provider.tsx similarity index 100% rename from web-app/components/instruments/runs-table/run-selection-provider.tsx rename to web/components/instruments/runs-table/run-selection-provider.tsx diff --git a/web-app/components/instruments/runs-table/run-status-icon.tsx b/web/components/instruments/runs-table/run-status-icon.tsx similarity index 100% rename from web-app/components/instruments/runs-table/run-status-icon.tsx rename to web/components/instruments/runs-table/run-status-icon.tsx diff --git a/web-app/components/instruments/runs-table/runs-table-footer.tsx b/web/components/instruments/runs-table/runs-table-footer.tsx similarity index 100% rename from web-app/components/instruments/runs-table/runs-table-footer.tsx rename to web/components/instruments/runs-table/runs-table-footer.tsx diff --git a/web-app/components/instruments/status-actions.tsx b/web/components/instruments/status-actions.tsx similarity index 100% rename from web-app/components/instruments/status-actions.tsx rename to web/components/instruments/status-actions.tsx diff --git a/web-app/components/pagination-nav.tsx b/web/components/pagination-nav.tsx similarity index 100% rename from web-app/components/pagination-nav.tsx rename to web/components/pagination-nav.tsx diff --git a/web-app/components/runs/archive-download-dialog.tsx b/web/components/runs/archive-download-dialog.tsx similarity index 100% rename from web-app/components/runs/archive-download-dialog.tsx rename to web/components/runs/archive-download-dialog.tsx diff --git a/web-app/components/runs/archive-download-provider.tsx b/web/components/runs/archive-download-provider.tsx similarity index 100% rename from web-app/components/runs/archive-download-provider.tsx rename to web/components/runs/archive-download-provider.tsx diff --git a/web-app/components/runs/comment-markdown.tsx b/web/components/runs/comment-markdown.tsx similarity index 100% rename from web-app/components/runs/comment-markdown.tsx rename to web/components/runs/comment-markdown.tsx diff --git a/web-app/components/runs/delete-run-dialog.tsx b/web/components/runs/delete-run-dialog.tsx similarity index 100% rename from web-app/components/runs/delete-run-dialog.tsx rename to web/components/runs/delete-run-dialog.tsx diff --git a/web-app/components/runs/delete-runs-dialog.tsx b/web/components/runs/delete-runs-dialog.tsx similarity index 100% rename from web-app/components/runs/delete-runs-dialog.tsx rename to web/components/runs/delete-runs-dialog.tsx diff --git a/web-app/components/runs/file-bulk-action-bar.tsx b/web/components/runs/file-bulk-action-bar.tsx similarity index 100% rename from web-app/components/runs/file-bulk-action-bar.tsx rename to web/components/runs/file-bulk-action-bar.tsx diff --git a/web-app/components/runs/file-select-checkbox.tsx b/web/components/runs/file-select-checkbox.tsx similarity index 100% rename from web-app/components/runs/file-select-checkbox.tsx rename to web/components/runs/file-select-checkbox.tsx diff --git a/web-app/components/runs/file-selection-provider.tsx b/web/components/runs/file-selection-provider.tsx similarity index 100% rename from web-app/components/runs/file-selection-provider.tsx rename to web/components/runs/file-selection-provider.tsx diff --git a/web-app/components/runs/file-status-badge.tsx b/web/components/runs/file-status-badge.tsx similarity index 100% rename from web-app/components/runs/file-status-badge.tsx rename to web/components/runs/file-status-badge.tsx diff --git a/web-app/components/runs/hina-report-section.tsx b/web/components/runs/hina-report-section.tsx similarity index 100% rename from web-app/components/runs/hina-report-section.tsx rename to web/components/runs/hina-report-section.tsx diff --git a/web-app/components/runs/metadata-badges.tsx b/web/components/runs/metadata-badges.tsx similarity index 100% rename from web-app/components/runs/metadata-badges.tsx rename to web/components/runs/metadata-badges.tsx diff --git a/web-app/components/runs/plate-map-grid.tsx b/web/components/runs/plate-map-grid.tsx similarity index 100% rename from web-app/components/runs/plate-map-grid.tsx rename to web/components/runs/plate-map-grid.tsx diff --git a/web-app/components/runs/raman-report-section.tsx b/web/components/runs/raman-report-section.tsx similarity index 100% rename from web-app/components/runs/raman-report-section.tsx rename to web/components/runs/raman-report-section.tsx diff --git a/web-app/components/runs/raman-spectrum-viewer.tsx b/web/components/runs/raman-spectrum-viewer.tsx similarity index 100% rename from web-app/components/runs/raman-spectrum-viewer.tsx rename to web/components/runs/raman-spectrum-viewer.tsx diff --git a/web-app/components/runs/reprocess-runs-dialog.tsx b/web/components/runs/reprocess-runs-dialog.tsx similarity index 100% rename from web-app/components/runs/reprocess-runs-dialog.tsx rename to web/components/runs/reprocess-runs-dialog.tsx diff --git a/web-app/components/runs/restore-run-button.tsx b/web/components/runs/restore-run-button.tsx similarity index 100% rename from web-app/components/runs/restore-run-button.tsx rename to web/components/runs/restore-run-button.tsx diff --git a/web-app/components/runs/run-attributions-section.tsx b/web/components/runs/run-attributions-section.tsx similarity index 100% rename from web-app/components/runs/run-attributions-section.tsx rename to web/components/runs/run-attributions-section.tsx diff --git a/web-app/components/runs/run-comment-form.tsx b/web/components/runs/run-comment-form.tsx similarity index 100% rename from web-app/components/runs/run-comment-form.tsx rename to web/components/runs/run-comment-form.tsx diff --git a/web-app/components/runs/run-comment-item.tsx b/web/components/runs/run-comment-item.tsx similarity index 100% rename from web-app/components/runs/run-comment-item.tsx rename to web/components/runs/run-comment-item.tsx diff --git a/web-app/components/runs/run-comments-list.tsx b/web/components/runs/run-comments-list.tsx similarity index 100% rename from web-app/components/runs/run-comments-list.tsx rename to web/components/runs/run-comments-list.tsx diff --git a/web-app/components/runs/run-comments-section.tsx b/web/components/runs/run-comments-section.tsx similarity index 100% rename from web-app/components/runs/run-comments-section.tsx rename to web/components/runs/run-comments-section.tsx diff --git a/web-app/components/runs/run-detail.ts b/web/components/runs/run-detail.ts similarity index 100% rename from web-app/components/runs/run-detail.ts rename to web/components/runs/run-detail.ts diff --git a/web-app/components/runs/run-files-metadata-layout.tsx b/web/components/runs/run-files-metadata-layout.tsx similarity index 100% rename from web-app/components/runs/run-files-metadata-layout.tsx rename to web/components/runs/run-files-metadata-layout.tsx diff --git a/web-app/components/runs/run-files-section.tsx b/web/components/runs/run-files-section.tsx similarity index 100% rename from web-app/components/runs/run-files-section.tsx rename to web/components/runs/run-files-section.tsx diff --git a/web-app/components/runs/run-files-table.tsx b/web/components/runs/run-files-table.tsx similarity index 100% rename from web-app/components/runs/run-files-table.tsx rename to web/components/runs/run-files-table.tsx diff --git a/web-app/components/runs/run-filters-combobox.tsx b/web/components/runs/run-filters-combobox.tsx similarity index 100% rename from web-app/components/runs/run-filters-combobox.tsx rename to web/components/runs/run-filters-combobox.tsx diff --git a/web-app/components/runs/run-header.tsx b/web/components/runs/run-header.tsx similarity index 100% rename from web-app/components/runs/run-header.tsx rename to web/components/runs/run-header.tsx diff --git a/web-app/components/runs/run-metadata-badges.tsx b/web/components/runs/run-metadata-badges.tsx similarity index 100% rename from web-app/components/runs/run-metadata-badges.tsx rename to web/components/runs/run-metadata-badges.tsx diff --git a/web-app/components/runs/run-metadata.tsx b/web/components/runs/run-metadata.tsx similarity index 100% rename from web-app/components/runs/run-metadata.tsx rename to web/components/runs/run-metadata.tsx diff --git a/web-app/components/runs/run-report-section.tsx b/web/components/runs/run-report-section.tsx similarity index 100% rename from web-app/components/runs/run-report-section.tsx rename to web/components/runs/run-report-section.tsx diff --git a/web-app/components/runs/runs-date-filter-calendar.tsx b/web/components/runs/runs-date-filter-calendar.tsx similarity index 100% rename from web-app/components/runs/runs-date-filter-calendar.tsx rename to web/components/runs/runs-date-filter-calendar.tsx diff --git a/web-app/components/runs/runs-date-filter.tsx b/web/components/runs/runs-date-filter.tsx similarity index 100% rename from web-app/components/runs/runs-date-filter.tsx rename to web/components/runs/runs-date-filter.tsx diff --git a/web-app/components/runs/variants/default-run-detail.tsx b/web/components/runs/variants/default-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/default-run-detail.tsx rename to web/components/runs/variants/default-run-detail.tsx diff --git a/web-app/components/runs/variants/epson-scanner-run-detail.tsx b/web/components/runs/variants/epson-scanner-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/epson-scanner-run-detail.tsx rename to web/components/runs/variants/epson-scanner-run-detail.tsx diff --git a/web-app/components/runs/variants/gel-doc-run-detail.tsx b/web/components/runs/variants/gel-doc-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/gel-doc-run-detail.tsx rename to web/components/runs/variants/gel-doc-run-detail.tsx diff --git a/web-app/components/runs/variants/hina-microscope-run-detail.tsx b/web/components/runs/variants/hina-microscope-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/hina-microscope-run-detail.tsx rename to web/components/runs/variants/hina-microscope-run-detail.tsx diff --git a/web-app/components/runs/variants/index.tsx b/web/components/runs/variants/index.tsx similarity index 100% rename from web-app/components/runs/variants/index.tsx rename to web/components/runs/variants/index.tsx diff --git a/web-app/components/runs/variants/instant-raman-run-detail.tsx b/web/components/runs/variants/instant-raman-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/instant-raman-run-detail.tsx rename to web/components/runs/variants/instant-raman-run-detail.tsx diff --git a/web-app/components/runs/variants/plate-reader-run-detail.tsx b/web/components/runs/variants/plate-reader-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/plate-reader-run-detail.tsx rename to web/components/runs/variants/plate-reader-run-detail.tsx diff --git a/web-app/components/runs/variants/qpcr-run-detail.tsx b/web/components/runs/variants/qpcr-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/qpcr-run-detail.tsx rename to web/components/runs/variants/qpcr-run-detail.tsx diff --git a/web-app/components/runs/variants/tape-station-run-detail.tsx b/web/components/runs/variants/tape-station-run-detail.tsx similarity index 100% rename from web-app/components/runs/variants/tape-station-run-detail.tsx rename to web/components/runs/variants/tape-station-run-detail.tsx diff --git a/web-app/components/runs/watcher-gated-upload-button.tsx b/web/components/runs/watcher-gated-upload-button.tsx similarity index 100% rename from web-app/components/runs/watcher-gated-upload-button.tsx rename to web/components/runs/watcher-gated-upload-button.tsx diff --git a/web-app/components/runs/watcher-status-provider.tsx b/web/components/runs/watcher-status-provider.tsx similarity index 100% rename from web-app/components/runs/watcher-status-provider.tsx rename to web/components/runs/watcher-status-provider.tsx diff --git a/web-app/components/table-pending.tsx b/web/components/table-pending.tsx similarity index 100% rename from web-app/components/table-pending.tsx rename to web/components/table-pending.tsx diff --git a/web-app/components/theme-provider.tsx b/web/components/theme-provider.tsx similarity index 100% rename from web-app/components/theme-provider.tsx rename to web/components/theme-provider.tsx diff --git a/web-app/components/tokens/create-token-dialog.tsx b/web/components/tokens/create-token-dialog.tsx similarity index 100% rename from web-app/components/tokens/create-token-dialog.tsx rename to web/components/tokens/create-token-dialog.tsx diff --git a/web-app/components/tokens/delete-token-dialog.tsx b/web/components/tokens/delete-token-dialog.tsx similarity index 100% rename from web-app/components/tokens/delete-token-dialog.tsx rename to web/components/tokens/delete-token-dialog.tsx diff --git a/web-app/components/ui/accordion.tsx b/web/components/ui/accordion.tsx similarity index 100% rename from web-app/components/ui/accordion.tsx rename to web/components/ui/accordion.tsx diff --git a/web-app/components/ui/alert-dialog.tsx b/web/components/ui/alert-dialog.tsx similarity index 100% rename from web-app/components/ui/alert-dialog.tsx rename to web/components/ui/alert-dialog.tsx diff --git a/web-app/components/ui/alert.tsx b/web/components/ui/alert.tsx similarity index 100% rename from web-app/components/ui/alert.tsx rename to web/components/ui/alert.tsx diff --git a/web-app/components/ui/avatar.tsx b/web/components/ui/avatar.tsx similarity index 100% rename from web-app/components/ui/avatar.tsx rename to web/components/ui/avatar.tsx diff --git a/web-app/components/ui/badge.tsx b/web/components/ui/badge.tsx similarity index 100% rename from web-app/components/ui/badge.tsx rename to web/components/ui/badge.tsx diff --git a/web-app/components/ui/breadcrumb.tsx b/web/components/ui/breadcrumb.tsx similarity index 100% rename from web-app/components/ui/breadcrumb.tsx rename to web/components/ui/breadcrumb.tsx diff --git a/web-app/components/ui/button.tsx b/web/components/ui/button.tsx similarity index 100% rename from web-app/components/ui/button.tsx rename to web/components/ui/button.tsx diff --git a/web-app/components/ui/calendar.tsx b/web/components/ui/calendar.tsx similarity index 100% rename from web-app/components/ui/calendar.tsx rename to web/components/ui/calendar.tsx diff --git a/web-app/components/ui/card.tsx b/web/components/ui/card.tsx similarity index 100% rename from web-app/components/ui/card.tsx rename to web/components/ui/card.tsx diff --git a/web-app/components/ui/carousel.tsx b/web/components/ui/carousel.tsx similarity index 100% rename from web-app/components/ui/carousel.tsx rename to web/components/ui/carousel.tsx diff --git a/web-app/components/ui/chart.tsx b/web/components/ui/chart.tsx similarity index 100% rename from web-app/components/ui/chart.tsx rename to web/components/ui/chart.tsx diff --git a/web-app/components/ui/checkbox.tsx b/web/components/ui/checkbox.tsx similarity index 100% rename from web-app/components/ui/checkbox.tsx rename to web/components/ui/checkbox.tsx diff --git a/web-app/components/ui/collapsible.tsx b/web/components/ui/collapsible.tsx similarity index 100% rename from web-app/components/ui/collapsible.tsx rename to web/components/ui/collapsible.tsx diff --git a/web-app/components/ui/command.tsx b/web/components/ui/command.tsx similarity index 100% rename from web-app/components/ui/command.tsx rename to web/components/ui/command.tsx diff --git a/web-app/components/ui/dialog.tsx b/web/components/ui/dialog.tsx similarity index 100% rename from web-app/components/ui/dialog.tsx rename to web/components/ui/dialog.tsx diff --git a/web-app/components/ui/dropdown-menu.tsx b/web/components/ui/dropdown-menu.tsx similarity index 100% rename from web-app/components/ui/dropdown-menu.tsx rename to web/components/ui/dropdown-menu.tsx diff --git a/web-app/components/ui/input-group.tsx b/web/components/ui/input-group.tsx similarity index 100% rename from web-app/components/ui/input-group.tsx rename to web/components/ui/input-group.tsx diff --git a/web-app/components/ui/input.tsx b/web/components/ui/input.tsx similarity index 100% rename from web-app/components/ui/input.tsx rename to web/components/ui/input.tsx diff --git a/web-app/components/ui/label.tsx b/web/components/ui/label.tsx similarity index 100% rename from web-app/components/ui/label.tsx rename to web/components/ui/label.tsx diff --git a/web-app/components/ui/pagination.tsx b/web/components/ui/pagination.tsx similarity index 100% rename from web-app/components/ui/pagination.tsx rename to web/components/ui/pagination.tsx diff --git a/web-app/components/ui/popover.tsx b/web/components/ui/popover.tsx similarity index 100% rename from web-app/components/ui/popover.tsx rename to web/components/ui/popover.tsx diff --git a/web-app/components/ui/scroll-area.tsx b/web/components/ui/scroll-area.tsx similarity index 100% rename from web-app/components/ui/scroll-area.tsx rename to web/components/ui/scroll-area.tsx diff --git a/web-app/components/ui/select.tsx b/web/components/ui/select.tsx similarity index 100% rename from web-app/components/ui/select.tsx rename to web/components/ui/select.tsx diff --git a/web-app/components/ui/separator.tsx b/web/components/ui/separator.tsx similarity index 100% rename from web-app/components/ui/separator.tsx rename to web/components/ui/separator.tsx diff --git a/web-app/components/ui/sheet.tsx b/web/components/ui/sheet.tsx similarity index 100% rename from web-app/components/ui/sheet.tsx rename to web/components/ui/sheet.tsx diff --git a/web-app/components/ui/sidebar.tsx b/web/components/ui/sidebar.tsx similarity index 100% rename from web-app/components/ui/sidebar.tsx rename to web/components/ui/sidebar.tsx diff --git a/web-app/components/ui/skeleton.tsx b/web/components/ui/skeleton.tsx similarity index 100% rename from web-app/components/ui/skeleton.tsx rename to web/components/ui/skeleton.tsx diff --git a/web-app/components/ui/slider.tsx b/web/components/ui/slider.tsx similarity index 100% rename from web-app/components/ui/slider.tsx rename to web/components/ui/slider.tsx diff --git a/web-app/components/ui/sonner.tsx b/web/components/ui/sonner.tsx similarity index 100% rename from web-app/components/ui/sonner.tsx rename to web/components/ui/sonner.tsx diff --git a/web-app/components/ui/switch.tsx b/web/components/ui/switch.tsx similarity index 100% rename from web-app/components/ui/switch.tsx rename to web/components/ui/switch.tsx diff --git a/web-app/components/ui/table.tsx b/web/components/ui/table.tsx similarity index 100% rename from web-app/components/ui/table.tsx rename to web/components/ui/table.tsx diff --git a/web-app/components/ui/tabs.tsx b/web/components/ui/tabs.tsx similarity index 100% rename from web-app/components/ui/tabs.tsx rename to web/components/ui/tabs.tsx diff --git a/web-app/components/ui/textarea.tsx b/web/components/ui/textarea.tsx similarity index 100% rename from web-app/components/ui/textarea.tsx rename to web/components/ui/textarea.tsx diff --git a/web-app/components/ui/toggle-group.tsx b/web/components/ui/toggle-group.tsx similarity index 100% rename from web-app/components/ui/toggle-group.tsx rename to web/components/ui/toggle-group.tsx diff --git a/web-app/components/ui/toggle.tsx b/web/components/ui/toggle.tsx similarity index 100% rename from web-app/components/ui/toggle.tsx rename to web/components/ui/toggle.tsx diff --git a/web-app/components/ui/tooltip.tsx b/web/components/ui/tooltip.tsx similarity index 100% rename from web-app/components/ui/tooltip.tsx rename to web/components/ui/tooltip.tsx diff --git a/web-app/components/watchers/deregister-dialog.tsx b/web/components/watchers/deregister-dialog.tsx similarity index 100% rename from web-app/components/watchers/deregister-dialog.tsx rename to web/components/watchers/deregister-dialog.tsx diff --git a/web-app/components/watchers/event-log-toolbar.tsx b/web/components/watchers/event-log-toolbar.tsx similarity index 100% rename from web-app/components/watchers/event-log-toolbar.tsx rename to web/components/watchers/event-log-toolbar.tsx diff --git a/web-app/components/watchers/event-log.tsx b/web/components/watchers/event-log.tsx similarity index 100% rename from web-app/components/watchers/event-log.tsx rename to web/components/watchers/event-log.tsx diff --git a/web-app/components/watchers/heartbeat-chart.tsx b/web/components/watchers/heartbeat-chart.tsx similarity index 100% rename from web-app/components/watchers/heartbeat-chart.tsx rename to web/components/watchers/heartbeat-chart.tsx diff --git a/web-app/components/watchers/status-toolbar.tsx b/web/components/watchers/status-toolbar.tsx similarity index 100% rename from web-app/components/watchers/status-toolbar.tsx rename to web/components/watchers/status-toolbar.tsx diff --git a/web-app/components/watchers/watcher-config.tsx b/web/components/watchers/watcher-config.tsx similarity index 100% rename from web-app/components/watchers/watcher-config.tsx rename to web/components/watchers/watcher-config.tsx diff --git a/web-app/components/watchers/watcher-detail-tabs.tsx b/web/components/watchers/watcher-detail-tabs.tsx similarity index 100% rename from web-app/components/watchers/watcher-detail-tabs.tsx rename to web/components/watchers/watcher-detail-tabs.tsx diff --git a/web-app/components/watchers/watcher-header.tsx b/web/components/watchers/watcher-header.tsx similarity index 100% rename from web-app/components/watchers/watcher-header.tsx rename to web/components/watchers/watcher-header.tsx diff --git a/web-app/components/watchers/watcher-online-status.ts b/web/components/watchers/watcher-online-status.ts similarity index 100% rename from web-app/components/watchers/watcher-online-status.ts rename to web/components/watchers/watcher-online-status.ts diff --git a/web-app/components/watchers/watcher-status-badge.tsx b/web/components/watchers/watcher-status-badge.tsx similarity index 100% rename from web-app/components/watchers/watcher-status-badge.tsx rename to web/components/watchers/watcher-status-badge.tsx diff --git a/web-app/components/watchers/watchers-table.tsx b/web/components/watchers/watchers-table.tsx similarity index 100% rename from web-app/components/watchers/watchers-table.tsx rename to web/components/watchers/watchers-table.tsx diff --git a/web-app/components/watchers/watchers-view.tsx b/web/components/watchers/watchers-view.tsx similarity index 100% rename from web-app/components/watchers/watchers-view.tsx rename to web/components/watchers/watchers-view.tsx diff --git a/web-app/drizzle.config.ts b/web/drizzle.config.ts similarity index 100% rename from web-app/drizzle.config.ts rename to web/drizzle.config.ts diff --git a/web-app/drizzle/0000_parched_the_santerians.sql b/web/drizzle/0000_parched_the_santerians.sql similarity index 100% rename from web-app/drizzle/0000_parched_the_santerians.sql rename to web/drizzle/0000_parched_the_santerians.sql diff --git a/web-app/drizzle/0001_wealthy_mathemanic.sql b/web/drizzle/0001_wealthy_mathemanic.sql similarity index 100% rename from web-app/drizzle/0001_wealthy_mathemanic.sql rename to web/drizzle/0001_wealthy_mathemanic.sql diff --git a/web-app/drizzle/0002_regular_emma_frost.sql b/web/drizzle/0002_regular_emma_frost.sql similarity index 100% rename from web-app/drizzle/0002_regular_emma_frost.sql rename to web/drizzle/0002_regular_emma_frost.sql diff --git a/web-app/drizzle/0003_productive_cannonball.sql b/web/drizzle/0003_productive_cannonball.sql similarity index 100% rename from web-app/drizzle/0003_productive_cannonball.sql rename to web/drizzle/0003_productive_cannonball.sql diff --git a/web-app/drizzle/0004_keen_gorilla_man.sql b/web/drizzle/0004_keen_gorilla_man.sql similarity index 100% rename from web-app/drizzle/0004_keen_gorilla_man.sql rename to web/drizzle/0004_keen_gorilla_man.sql diff --git a/web-app/drizzle/0005_drop_s3_trigger_suffix.sql b/web/drizzle/0005_drop_s3_trigger_suffix.sql similarity index 100% rename from web-app/drizzle/0005_drop_s3_trigger_suffix.sql rename to web/drizzle/0005_drop_s3_trigger_suffix.sql diff --git a/web-app/drizzle/0006_qpcr_tape_station.sql b/web/drizzle/0006_qpcr_tape_station.sql similarity index 100% rename from web-app/drizzle/0006_qpcr_tape_station.sql rename to web/drizzle/0006_qpcr_tape_station.sql diff --git a/web-app/drizzle/0007_dazzling_hercules.sql b/web/drizzle/0007_dazzling_hercules.sql similarity index 100% rename from web-app/drizzle/0007_dazzling_hercules.sql rename to web/drizzle/0007_dazzling_hercules.sql diff --git a/web-app/drizzle/0008_chilly_princess_powerful.sql b/web/drizzle/0008_chilly_princess_powerful.sql similarity index 100% rename from web-app/drizzle/0008_chilly_princess_powerful.sql rename to web/drizzle/0008_chilly_princess_powerful.sql diff --git a/web-app/drizzle/0009_clammy_tyger_tiger.sql b/web/drizzle/0009_clammy_tyger_tiger.sql similarity index 100% rename from web-app/drizzle/0009_clammy_tyger_tiger.sql rename to web/drizzle/0009_clammy_tyger_tiger.sql diff --git a/web-app/drizzle/0010_enforce_active_watcher_unique.sql b/web/drizzle/0010_enforce_active_watcher_unique.sql similarity index 100% rename from web-app/drizzle/0010_enforce_active_watcher_unique.sql rename to web/drizzle/0010_enforce_active_watcher_unique.sql diff --git a/web-app/drizzle/0011_clever_power_pack.sql b/web/drizzle/0011_clever_power_pack.sql similarity index 100% rename from web-app/drizzle/0011_clever_power_pack.sql rename to web/drizzle/0011_clever_power_pack.sql diff --git a/web-app/drizzle/0012_drop_redundant_idx_files_active.sql b/web/drizzle/0012_drop_redundant_idx_files_active.sql similarity index 100% rename from web-app/drizzle/0012_drop_redundant_idx_files_active.sql rename to web/drizzle/0012_drop_redundant_idx_files_active.sql diff --git a/web-app/drizzle/0013_add_watcher_version.sql b/web/drizzle/0013_add_watcher_version.sql similarity index 100% rename from web-app/drizzle/0013_add_watcher_version.sql rename to web/drizzle/0013_add_watcher_version.sql diff --git a/web-app/drizzle/0014_add_watcher_update_events.sql b/web/drizzle/0014_add_watcher_update_events.sql similarity index 100% rename from web-app/drizzle/0014_add_watcher_update_events.sql rename to web/drizzle/0014_add_watcher_update_events.sql diff --git a/web-app/drizzle/0015_empty_kitty_pryde.sql b/web/drizzle/0015_empty_kitty_pryde.sql similarity index 100% rename from web-app/drizzle/0015_empty_kitty_pryde.sql rename to web/drizzle/0015_empty_kitty_pryde.sql diff --git a/web-app/drizzle/0016_add_archive_jobs.sql b/web/drizzle/0016_add_archive_jobs.sql similarity index 100% rename from web-app/drizzle/0016_add_archive_jobs.sql rename to web/drizzle/0016_add_archive_jobs.sql diff --git a/web-app/drizzle/0017_drop_files_purged_at.sql b/web/drizzle/0017_drop_files_purged_at.sql similarity index 100% rename from web-app/drizzle/0017_drop_files_purged_at.sql rename to web/drizzle/0017_drop_files_purged_at.sql diff --git a/web-app/drizzle/0018_epson_v700_scanner_type.sql b/web/drizzle/0018_epson_v700_scanner_type.sql similarity index 100% rename from web-app/drizzle/0018_epson_v700_scanner_type.sql rename to web/drizzle/0018_epson_v700_scanner_type.sql diff --git a/web-app/drizzle/0019_set_epson_scanner_type.sql b/web/drizzle/0019_set_epson_scanner_type.sql similarity index 100% rename from web-app/drizzle/0019_set_epson_scanner_type.sql rename to web/drizzle/0019_set_epson_scanner_type.sql diff --git a/web-app/drizzle/0020_add_acquired_at.sql b/web/drizzle/0020_add_acquired_at.sql similarity index 100% rename from web-app/drizzle/0020_add_acquired_at.sql rename to web/drizzle/0020_add_acquired_at.sql diff --git a/web-app/drizzle/0021_instant_raman_type.sql b/web/drizzle/0021_instant_raman_type.sql similarity index 100% rename from web-app/drizzle/0021_instant_raman_type.sql rename to web/drizzle/0021_instant_raman_type.sql diff --git a/web-app/drizzle/0022_pat_scopes.sql b/web/drizzle/0022_pat_scopes.sql similarity index 100% rename from web-app/drizzle/0022_pat_scopes.sql rename to web/drizzle/0022_pat_scopes.sql diff --git a/web-app/drizzle/meta/0000_snapshot.json b/web/drizzle/meta/0000_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0000_snapshot.json rename to web/drizzle/meta/0000_snapshot.json diff --git a/web-app/drizzle/meta/0001_snapshot.json b/web/drizzle/meta/0001_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0001_snapshot.json rename to web/drizzle/meta/0001_snapshot.json diff --git a/web-app/drizzle/meta/0002_snapshot.json b/web/drizzle/meta/0002_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0002_snapshot.json rename to web/drizzle/meta/0002_snapshot.json diff --git a/web-app/drizzle/meta/0003_snapshot.json b/web/drizzle/meta/0003_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0003_snapshot.json rename to web/drizzle/meta/0003_snapshot.json diff --git a/web-app/drizzle/meta/0004_snapshot.json b/web/drizzle/meta/0004_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0004_snapshot.json rename to web/drizzle/meta/0004_snapshot.json diff --git a/web-app/drizzle/meta/0005_snapshot.json b/web/drizzle/meta/0005_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0005_snapshot.json rename to web/drizzle/meta/0005_snapshot.json diff --git a/web-app/drizzle/meta/0006_snapshot.json b/web/drizzle/meta/0006_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0006_snapshot.json rename to web/drizzle/meta/0006_snapshot.json diff --git a/web-app/drizzle/meta/0007_snapshot.json b/web/drizzle/meta/0007_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0007_snapshot.json rename to web/drizzle/meta/0007_snapshot.json diff --git a/web-app/drizzle/meta/0008_snapshot.json b/web/drizzle/meta/0008_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0008_snapshot.json rename to web/drizzle/meta/0008_snapshot.json diff --git a/web-app/drizzle/meta/0009_snapshot.json b/web/drizzle/meta/0009_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0009_snapshot.json rename to web/drizzle/meta/0009_snapshot.json diff --git a/web-app/drizzle/meta/0010_snapshot.json b/web/drizzle/meta/0010_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0010_snapshot.json rename to web/drizzle/meta/0010_snapshot.json diff --git a/web-app/drizzle/meta/0011_snapshot.json b/web/drizzle/meta/0011_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0011_snapshot.json rename to web/drizzle/meta/0011_snapshot.json diff --git a/web-app/drizzle/meta/0012_snapshot.json b/web/drizzle/meta/0012_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0012_snapshot.json rename to web/drizzle/meta/0012_snapshot.json diff --git a/web-app/drizzle/meta/0013_snapshot.json b/web/drizzle/meta/0013_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0013_snapshot.json rename to web/drizzle/meta/0013_snapshot.json diff --git a/web-app/drizzle/meta/0014_snapshot.json b/web/drizzle/meta/0014_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0014_snapshot.json rename to web/drizzle/meta/0014_snapshot.json diff --git a/web-app/drizzle/meta/0015_snapshot.json b/web/drizzle/meta/0015_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0015_snapshot.json rename to web/drizzle/meta/0015_snapshot.json diff --git a/web-app/drizzle/meta/0016_snapshot.json b/web/drizzle/meta/0016_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0016_snapshot.json rename to web/drizzle/meta/0016_snapshot.json diff --git a/web-app/drizzle/meta/0017_snapshot.json b/web/drizzle/meta/0017_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0017_snapshot.json rename to web/drizzle/meta/0017_snapshot.json diff --git a/web-app/drizzle/meta/0018_snapshot.json b/web/drizzle/meta/0018_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0018_snapshot.json rename to web/drizzle/meta/0018_snapshot.json diff --git a/web-app/drizzle/meta/0019_snapshot.json b/web/drizzle/meta/0019_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0019_snapshot.json rename to web/drizzle/meta/0019_snapshot.json diff --git a/web-app/drizzle/meta/0020_snapshot.json b/web/drizzle/meta/0020_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0020_snapshot.json rename to web/drizzle/meta/0020_snapshot.json diff --git a/web-app/drizzle/meta/0021_snapshot.json b/web/drizzle/meta/0021_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0021_snapshot.json rename to web/drizzle/meta/0021_snapshot.json diff --git a/web-app/drizzle/meta/0022_snapshot.json b/web/drizzle/meta/0022_snapshot.json similarity index 100% rename from web-app/drizzle/meta/0022_snapshot.json rename to web/drizzle/meta/0022_snapshot.json diff --git a/web-app/drizzle/meta/_journal.json b/web/drizzle/meta/_journal.json similarity index 100% rename from web-app/drizzle/meta/_journal.json rename to web/drizzle/meta/_journal.json diff --git a/web-app/eslint.config.mjs b/web/eslint.config.mjs similarity index 100% rename from web-app/eslint.config.mjs rename to web/eslint.config.mjs diff --git a/web-app/hooks/.gitkeep b/web/hooks/.gitkeep similarity index 100% rename from web-app/hooks/.gitkeep rename to web/hooks/.gitkeep diff --git a/web-app/hooks/use-archive-download.ts b/web/hooks/use-archive-download.ts similarity index 100% rename from web-app/hooks/use-archive-download.ts rename to web/hooks/use-archive-download.ts diff --git a/web-app/hooks/use-mobile.ts b/web/hooks/use-mobile.ts similarity index 100% rename from web-app/hooks/use-mobile.ts rename to web/hooks/use-mobile.ts diff --git a/web-app/lib/api/archive-builder.ts b/web/lib/api/archive-builder.ts similarity index 100% rename from web-app/lib/api/archive-builder.ts rename to web/lib/api/archive-builder.ts diff --git a/web-app/lib/api/archive-jobs.ts b/web/lib/api/archive-jobs.ts similarity index 100% rename from web-app/lib/api/archive-jobs.ts rename to web/lib/api/archive-jobs.ts diff --git a/web-app/lib/api/auth.ts b/web/lib/api/auth.ts similarity index 100% rename from web-app/lib/api/auth.ts rename to web/lib/api/auth.ts diff --git a/web-app/lib/api/dashboard.ts b/web/lib/api/dashboard.ts similarity index 100% rename from web-app/lib/api/dashboard.ts rename to web/lib/api/dashboard.ts diff --git a/web-app/lib/api/errors.ts b/web/lib/api/errors.ts similarity index 100% rename from web-app/lib/api/errors.ts rename to web/lib/api/errors.ts diff --git a/web-app/lib/api/file-reprocessing.ts b/web/lib/api/file-reprocessing.ts similarity index 100% rename from web-app/lib/api/file-reprocessing.ts rename to web/lib/api/file-reprocessing.ts diff --git a/web-app/lib/api/files.ts b/web/lib/api/files.ts similarity index 100% rename from web-app/lib/api/files.ts rename to web/lib/api/files.ts diff --git a/web-app/lib/api/instrument-runs.ts b/web/lib/api/instrument-runs.ts similarity index 100% rename from web-app/lib/api/instrument-runs.ts rename to web/lib/api/instrument-runs.ts diff --git a/web-app/lib/api/instruments.ts b/web/lib/api/instruments.ts similarity index 100% rename from web-app/lib/api/instruments.ts rename to web/lib/api/instruments.ts diff --git a/web-app/lib/api/run-comments.ts b/web/lib/api/run-comments.ts similarity index 100% rename from web-app/lib/api/run-comments.ts rename to web/lib/api/run-comments.ts diff --git a/web-app/lib/api/scopes.ts b/web/lib/api/scopes.ts similarity index 100% rename from web-app/lib/api/scopes.ts rename to web/lib/api/scopes.ts diff --git a/web-app/lib/api/sidebar.ts b/web/lib/api/sidebar.ts similarity index 100% rename from web-app/lib/api/sidebar.ts rename to web/lib/api/sidebar.ts diff --git a/web-app/lib/api/validators.ts b/web/lib/api/validators.ts similarity index 100% rename from web-app/lib/api/validators.ts rename to web/lib/api/validators.ts diff --git a/web-app/lib/api/watchers.ts b/web/lib/api/watchers.ts similarity index 100% rename from web-app/lib/api/watchers.ts rename to web/lib/api/watchers.ts diff --git a/web-app/lib/auth.ts b/web/lib/auth.ts similarity index 100% rename from web-app/lib/auth.ts rename to web/lib/auth.ts diff --git a/web-app/lib/date.ts b/web/lib/date.ts similarity index 100% rename from web-app/lib/date.ts rename to web/lib/date.ts diff --git a/web-app/lib/db/index.ts b/web/lib/db/index.ts similarity index 100% rename from web-app/lib/db/index.ts rename to web/lib/db/index.ts diff --git a/web-app/lib/db/schema.ts b/web/lib/db/schema.ts similarity index 100% rename from web-app/lib/db/schema.ts rename to web/lib/db/schema.ts diff --git a/web-app/lib/instrument-colors.ts b/web/lib/instrument-colors.ts similarity index 100% rename from web-app/lib/instrument-colors.ts rename to web/lib/instrument-colors.ts diff --git a/web-app/lib/lambda.ts b/web/lib/lambda.ts similarity index 100% rename from web-app/lib/lambda.ts rename to web/lib/lambda.ts diff --git a/web-app/lib/mcp/prompts.ts b/web/lib/mcp/prompts.ts similarity index 100% rename from web-app/lib/mcp/prompts.ts rename to web/lib/mcp/prompts.ts diff --git a/web-app/lib/mcp/resources.ts b/web/lib/mcp/resources.ts similarity index 100% rename from web-app/lib/mcp/resources.ts rename to web/lib/mcp/resources.ts diff --git a/web-app/lib/mcp/tools.ts b/web/lib/mcp/tools.ts similarity index 100% rename from web-app/lib/mcp/tools.ts rename to web/lib/mcp/tools.ts diff --git a/web-app/lib/runs/row-actions.ts b/web/lib/runs/row-actions.ts similarity index 100% rename from web-app/lib/runs/row-actions.ts rename to web/lib/runs/row-actions.ts diff --git a/web-app/lib/s3.ts b/web/lib/s3.ts similarity index 100% rename from web-app/lib/s3.ts rename to web/lib/s3.ts diff --git a/web-app/lib/search-params.ts b/web/lib/search-params.ts similarity index 100% rename from web-app/lib/search-params.ts rename to web/lib/search-params.ts diff --git a/web-app/lib/slack.ts b/web/lib/slack.ts similarity index 100% rename from web-app/lib/slack.ts rename to web/lib/slack.ts diff --git a/web-app/lib/tokens.ts b/web/lib/tokens.ts similarity index 100% rename from web-app/lib/tokens.ts rename to web/lib/tokens.ts diff --git a/web-app/lib/utils.ts b/web/lib/utils.ts similarity index 100% rename from web-app/lib/utils.ts rename to web/lib/utils.ts diff --git a/web-app/next.config.mjs b/web/next.config.mjs similarity index 100% rename from web-app/next.config.mjs rename to web/next.config.mjs diff --git a/web-app/package-lock.json b/web/package-lock.json similarity index 99% rename from web-app/package-lock.json rename to web/package-lock.json index 363a82ff..ab38e549 100644 --- a/web-app/package-lock.json +++ b/web/package-lock.json @@ -1,11 +1,11 @@ { - "name": "data-hub-web-app", + "name": "data-hub-web", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "data-hub-web-app", + "name": "data-hub-web", "version": "0.0.1", "dependencies": { "@auth/drizzle-adapter": "^1.11.1", @@ -6703,6 +6703,70 @@ "node": ">=14.0.0" } }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/core": { + "version": "1.8.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/wasi-threads": "1.1.0", + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/runtime": { + "version": "1.8.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@emnapi/wasi-threads": { + "version": "1.1.0", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@napi-rs/wasm-runtime": { + "version": "1.1.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@emnapi/core": "^1.7.1", + "@emnapi/runtime": "^1.7.1", + "@tybys/wasm-util": "^0.10.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/Brooooooklyn" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/@tybys/wasm-util": { + "version": "0.10.1", + "dev": true, + "inBundle": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi/node_modules/tslib": { + "version": "2.8.1", + "dev": true, + "inBundle": true, + "license": "0BSD", + "optional": true + }, "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.2.2.tgz", diff --git a/web-app/package.json b/web/package.json similarity index 98% rename from web-app/package.json rename to web/package.json index 1a5fbd83..d26a0532 100644 --- a/web-app/package.json +++ b/web/package.json @@ -1,5 +1,5 @@ { - "name": "data-hub-web-app", + "name": "data-hub-web", "version": "0.0.1", "type": "module", "private": true, diff --git a/web-app/postcss.config.mjs b/web/postcss.config.mjs similarity index 100% rename from web-app/postcss.config.mjs rename to web/postcss.config.mjs diff --git a/web-app/proxy.ts b/web/proxy.ts similarity index 100% rename from web-app/proxy.ts rename to web/proxy.ts diff --git a/web-app/public/images/data-hub-logo.svg b/web/public/images/data-hub-logo.svg similarity index 100% rename from web-app/public/images/data-hub-logo.svg rename to web/public/images/data-hub-logo.svg diff --git a/web-app/scripts/README.md b/web/scripts/README.md similarity index 100% rename from web-app/scripts/README.md rename to web/scripts/README.md diff --git a/web-app/scripts/reset-database.ts b/web/scripts/reset-database.ts similarity index 100% rename from web-app/scripts/reset-database.ts rename to web/scripts/reset-database.ts diff --git a/web-app/tests/integration/archive-jobs.test.ts b/web/tests/integration/archive-jobs.test.ts similarity index 99% rename from web-app/tests/integration/archive-jobs.test.ts rename to web/tests/integration/archive-jobs.test.ts index 38767693..fb55f2bf 100644 --- a/web-app/tests/integration/archive-jobs.test.ts +++ b/web/tests/integration/archive-jobs.test.ts @@ -17,7 +17,7 @@ import { afterAll, beforeAll, describe, expect, it } from "vitest"; // Tests for the /api/v1/archive-jobs/:id PATCH callback the Lambda fires // when a build finishes. The UI doesn't poll this endpoint — it re-issues // /download-archive instead — so there is no GET handler on this route; -// only the Lambda → web-app callback. The actual zip building is exercised +// only the Lambda → web app callback. The actual zip building is exercised // by Lambda unit tests; here we focus on auth, validation, state // transitions, the partial-unique-index dedup, and the stuck-row sweep. describe("Archive Jobs API", () => { diff --git a/web-app/tests/integration/auth.test.ts b/web/tests/integration/auth.test.ts similarity index 100% rename from web-app/tests/integration/auth.test.ts rename to web/tests/integration/auth.test.ts diff --git a/web-app/tests/integration/files.test.ts b/web/tests/integration/files.test.ts similarity index 100% rename from web-app/tests/integration/files.test.ts rename to web/tests/integration/files.test.ts diff --git a/web-app/tests/integration/global-setup.ts b/web/tests/integration/global-setup.ts similarity index 100% rename from web-app/tests/integration/global-setup.ts rename to web/tests/integration/global-setup.ts diff --git a/web-app/tests/integration/helpers.ts b/web/tests/integration/helpers.ts similarity index 100% rename from web-app/tests/integration/helpers.ts rename to web/tests/integration/helpers.ts diff --git a/web-app/tests/integration/instrument-runs.test.ts b/web/tests/integration/instrument-runs.test.ts similarity index 100% rename from web-app/tests/integration/instrument-runs.test.ts rename to web/tests/integration/instrument-runs.test.ts diff --git a/web-app/tests/integration/instruments.test.ts b/web/tests/integration/instruments.test.ts similarity index 100% rename from web-app/tests/integration/instruments.test.ts rename to web/tests/integration/instruments.test.ts diff --git a/web-app/tests/integration/mcp.test.ts b/web/tests/integration/mcp.test.ts similarity index 100% rename from web-app/tests/integration/mcp.test.ts rename to web/tests/integration/mcp.test.ts diff --git a/web-app/tests/integration/request-upload-url.test.ts b/web/tests/integration/request-upload-url.test.ts similarity index 100% rename from web-app/tests/integration/request-upload-url.test.ts rename to web/tests/integration/request-upload-url.test.ts diff --git a/web-app/tests/integration/run-attributions.test.ts b/web/tests/integration/run-attributions.test.ts similarity index 100% rename from web-app/tests/integration/run-attributions.test.ts rename to web/tests/integration/run-attributions.test.ts diff --git a/web-app/tests/integration/run-comments.test.ts b/web/tests/integration/run-comments.test.ts similarity index 100% rename from web-app/tests/integration/run-comments.test.ts rename to web/tests/integration/run-comments.test.ts diff --git a/web-app/tests/integration/scopes.test.ts b/web/tests/integration/scopes.test.ts similarity index 100% rename from web-app/tests/integration/scopes.test.ts rename to web/tests/integration/scopes.test.ts diff --git a/web-app/tests/integration/watchers.test.ts b/web/tests/integration/watchers.test.ts similarity index 100% rename from web-app/tests/integration/watchers.test.ts rename to web/tests/integration/watchers.test.ts diff --git a/web-app/tests/mcp/mcp-protocol.test.ts b/web/tests/mcp/mcp-protocol.test.ts similarity index 100% rename from web-app/tests/mcp/mcp-protocol.test.ts rename to web/tests/mcp/mcp-protocol.test.ts diff --git a/web-app/tests/unit/scope-validation.test.ts b/web/tests/unit/scope-validation.test.ts similarity index 100% rename from web-app/tests/unit/scope-validation.test.ts rename to web/tests/unit/scope-validation.test.ts diff --git a/web-app/tsconfig.json b/web/tsconfig.json similarity index 100% rename from web-app/tsconfig.json rename to web/tsconfig.json diff --git a/web-app/vitest.config.ts b/web/vitest.config.ts similarity index 100% rename from web-app/vitest.config.ts rename to web/vitest.config.ts diff --git a/web-app/vitest.integration.config.ts b/web/vitest.integration.config.ts similarity index 100% rename from web-app/vitest.integration.config.ts rename to web/vitest.integration.config.ts