Repository Layout (detail)¶
Extracted from
.github/copilot-instructions.md§4 on 2026-05-19 to keep the always-loaded charter lean. Read this on demand when you need the full tree.
Create directories on demand; do not scaffold empty folders speculatively.
.
├── api/ # Backend — FastAPI for the `api` sidecar + Celery worker/beat
│ ├── main.py # FastAPI app entrypoint (uvicorn target)
│ ├── celery_app.py # Celery app + queue routing
│ ├── auth.py # MSAL bearer token validation
│ ├── _http_utils.py # Shared HTTP boundary helpers
│ ├── routes/ # FastAPI routers (arm, monitor, resources, terminal_ws, frontend_proxy, …)
│ ├── services/ # Pure-Python wrappers (azure_clients, monitoring, state_repo, sanitise, image_tags, …)
│ ├── tasks/ # Celery task modules (BLAST submit/delete, ACR build, AKS provision, schedules)
│ ├── tests/ # pytest (FastAPI + Celery + shared service modules)
│ ├── Dockerfile # Image used by both `api` and `worker`/`beat` sidecars
│ └── requirements.txt
├── web/ # React + Vite + TypeScript SPA + Dockerfile + nginx.conf for the `frontend` sidecar
│ ├── src/
│ │ ├── components/ # Glassmorphic UI building blocks
│ │ ├── pages/ # Dashboard, BrowserTerminal, JobDetail, …
│ │ ├── hooks/
│ │ ├── api/ # Typed fetchers for /api routes
│ │ └── theme/ # Glassmorphism tokens (CSS variables)
│ ├── nginx.conf # nginx config for the `frontend` sidecar
│ └── vite.config.ts
├── terminal/ # Dockerfile + entrypoint for the `terminal` sidecar (ttyd + elastic-blast toolchain)
├── infra/ # Bicep modules + main.bicep
│ ├── main.bicep # Container Apps Environment + ca-elb-dashboard + private networking
│ └── modules/ # containerApp.bicep, network.bicep, identity.bicep, acr.bicep, storage.bicep, keyVault.bicep, …
├── scripts/
│ └── dev/ # Local dev helpers + postprovision.sh (runs `az acr build` and swaps the Container App template)
├── docs/
│ ├── auth.md
│ ├── container-apps-migration.md # Authoritative target architecture
│ ├── copilot/ # On-demand detail for Copilot instructions (this folder)
│ └── features_change/ # Per-change notes
├── tests/ # Cross-cutting tests; per-component tests live next to their code
├── azure.yaml # azd manifest (Bicep provider + pre/postprovision hooks)
└── README.md
Quick reference — Where things live¶
| Need to… | Edit |
|---|---|
| Add a new monitoring card | web/src/pages/Dashboard.tsx + a new route in api/routes/monitor.py |
| Add a new HTTP route | api/routes/<area>.py + register in api/main.py |
| Add a new long-running operation | api/tasks/<area>.py (Celery task) + an enqueue endpoint in api/routes/ |
| Change tools installed in the terminal | terminal/Dockerfile + terminal/entrypoint.sh |
| Bump pinned ACR image tags | api/services/image_tags.py (IMAGE_TAGS dict) |
| Adjust glass styling | web/src/theme/glass.css |
| Add a new Bicep resource | infra/modules/*.bicep + wire into infra/main.bicep |
| Change Container App sidecar layout | infra/modules/containerApp.bicep (or the template diff applied by scripts/dev/postprovision.sh) |
| Document a behaviour change | docs/features_change/YYYY-MM/…md (mandatory) |
For deeper navigation (route map, tripwires) see AGENTS.md.
Backend module map (api/)¶
api/
├── main.py # FastAPI app factory + middleware (RequestId, structured logs)
├── celery_app.py # Celery app + queue routing (azure / blast / storage / default)
├── auth.py # MSAL bearer-token validation (OIDC discovery + JWKS cache)
├── conftest.py # pytest sys.path bootstrap
├── routes/ # FastAPI routers (one file per /api/<area>)
├── services/ # The ONLY place that touches azure.mgmt.* / azure.identity / k8s
│ ├── azure_clients.py # Cached Azure SDK client factories (MI under DefaultAzureCredential)
│ ├── monitoring.py # AKS / Storage / ACR readers + k8s_* kubelet helpers
│ ├── network.py # ensure_resource_group + VNet/Subnet/NSG primitives
│ ├── compute.py # VM lifecycle helpers (only used by legacy code paths now)
│ ├── keyvault.py # KV secret read/write
│ ├── storage_data.py # Blob upload/list/read — NO SAS issuance, see charter §9 footgun note
│ ├── state_repo.py # JobStateRepository (Table Storage + append-blob audit)
│ ├── sanitise.py # Output redactor (SAS, bearer, sub-id, secrets) — apply at every UI boundary
│ ├── passwords.py # generate_admin_password (used only by legacy, kept for tests)
│ ├── ssh_exec.py # paramiko helpers (used only by legacy)
│ ├── blast_config.py # Azure SKU / pricing constants
│ └── image_tags.py # IMAGE_TAGS dict — bump in sync with sibling repo
├── tasks/ # Celery tasks live here (mostly empty; populate as you implement stub routes)
└── tests/ # `uv run pytest -q api/tests`
Frontend module map (web/src/)¶
web/src/
├── App.tsx, main.tsx # Router + MSAL provider wiring
├── api/
│ ├── client.ts # fetch wrapper that injects MSAL bearer
│ ├── endpoints.ts # Typed endpoint helpers (one source of /api/* surface)
│ ├── arm.ts # Direct ARM token flow (used only where SPA needs subscription list)
│ ├── callerIp.ts # Browser → ipify (caller IP capture)
│ └── resilience.ts # Retry / backoff helpers + tests
├── auth/ # MSAL configuration
├── components/ # Reusable glass cards, modals, etc.
├── pages/ # Dashboard, BlastJobs, BlastResults, BlastAnalytics, RemoteTerminal, ...
├── hooks/, data/, theme/, constants.ts
UI tokens (glassmorphism) are CSS variables; see docs/copilot/glass-ui.md.
Infra map (infra/)¶
infra/main.bicep wires nine modules in this order:
network → monitoring → identity → acr → storage → storageState → keyvault →
containerEnv → controlApp. Each one is a single small file under
infra/modules/.
Public ingress lands on the api sidecar at :8080. All other sidecars
listen on loopback only:
- frontend nginx → 127.0.0.1:8081
- terminal ttyd → 127.0.0.1:7681
- redis → 127.0.0.1:6379