Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 26 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,19 @@ Migration note:
- `GET /api/analysis-runs/{run_id}`
- `GET /api/analysis-runs/{run_id}/artifacts...`

Runtime profiles:

- `local`: current local/dev mode with SQLite + local artifact files + in-process workers.
- `hosted`: hosted-service mode with auth hooks and worker separation boundaries.

In plain English: the analysis engine is still shared, but the repo now has an explicit split between local mode and hosted mode so public-hosting work does not have to change the local product path.

Artifact storage now sits behind a backend storage service boundary. In plain English: ASA still writes files locally today, but the code is no longer hard-wired to assume that every stored artifact is just a disk path on the same machine.

Implementation record:

- see `docs/PUBLIC_HOSTING_FOUNDATION.md` for the full summary of the hosted-foundation work, the follow-up fixes, the verification that was run, and the remaining work before any true public deployment.

Legacy `POST /api/analyze`, `POST /api/analyze/estimate`, and `POST /api/phase2` remain available only as temporary compatibility wrappers during the migration window.

## Local Setup
Expand Down Expand Up @@ -89,6 +102,12 @@ VITE_API_BASE_URL="http://127.0.0.1:8100"
VITE_ENABLE_PHASE2_GEMINI="true"
```

Optional hosted-mode request-header bootstrap for private beta testing:

```bash
VITE_API_REQUEST_HEADERS_JSON='{"X-ASA-User-Id":"beta-user-123"}'
```

Supported shell-based overrides:

```bash
Expand All @@ -115,6 +134,13 @@ cd apps/backend
SONIC_ANALYZER_PORT=8100 ./venv/bin/python server.py
```

Hosted worker process:

```bash
cd apps/backend
SONIC_ANALYZER_RUNTIME_PROFILE=hosted SONIC_ANALYZER_PROCESS_ROLE=worker ./venv/bin/python worker.py
```

```bash
cd apps/ui
VITE_API_BASE_URL=http://127.0.0.1:8100 npm run dev:local
Expand Down
30 changes: 23 additions & 7 deletions apps/backend/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
| Component | Role |
| --- | --- |
| `analyze.py` | Raw CLI analyzer. Loads audio, runs DSP, optionally separates stems and transcribes notes through torchcrepe, then prints JSON to `stdout`. |
| `server.py` | FastAPI wrapper. Accepts uploads, computes an estimate, shells out to `analyze.py`, normalizes the result into the HTTP `phase1` contract, and returns diagnostics or structured errors. |
| `server.py` | FastAPI wrapper. Accepts uploads, computes estimates, manages the canonical staged run API, normalizes measurement results, and serves artifact access. |
| `analysis_runtime.py` | Run-state persistence and staged-analysis orchestration. Owns run snapshots, stage status, artifact metadata, and ownership checks. |
| `artifact_storage.py` | Artifact storage boundary. The current implementation uses the local filesystem, but the runtime now talks to a storage service interface instead of assuming every artifact is a local disk path forever. |
| `runtime_profile.py` | Runtime/profile switchboard for `local` vs `hosted` behavior and `all` vs `api` vs `worker` process roles. |
| `auth_context.py` | Hosted-mode user-context resolution. Establishes the current run owner in the canonical API path. |
| `worker.py` | Dedicated worker-process entry point for hosted-style background stage execution. |
| `tests/test_server.py` | Contract tests for estimate, timeout, and success envelopes. |
| `spectral_viz.py` | Librosa-based spectrogram generation and spectral time-series extraction. Produces mel/chroma PNG spectrograms and per-frame spectral evolution JSON. Called after successful measurement; failures are non-critical. |
| `tests/test_analyze.py` | Structural snapshot tests for the raw analyzer JSON output. |
Expand Down Expand Up @@ -34,18 +39,20 @@ Interface:
Responsibilities:

- receive multipart uploads
- write the upload to a temporary file
- compute a backend estimate and timeout
- invoke `analyze.py` with `--yes`
- translate raw analyzer output into the HTTP `phase1` envelope
- return structured error diagnostics when the subprocess fails
- clean up temporary files
- write uploads to the runtime through the canonical run path
- compute backend estimates and timeouts
- invoke `analyze.py` with `--yes` through worker-owned stage execution
- translate raw analyzer output into the canonical measurement envelope
- enforce hosted-mode ownership on canonical run routes
- serve artifact metadata and artifact downloads without leaking internal paths
- return structured error diagnostics when subprocess execution fails

Custom routes:

- `POST /api/analysis-runs/estimate`
- `POST /api/analysis-runs`
- `GET /api/analysis-runs/{run_id}`
- `DELETE /api/analysis-runs/{run_id}`
- `POST /api/analyze` (legacy compatibility)
- `POST /api/analyze/estimate` (legacy compatibility)
- `POST /api/phase2` (legacy compatibility)
Expand Down Expand Up @@ -119,6 +126,15 @@ Important sections:
9. On success, normalize the raw payload into `phase1` and attach diagnostics.
10. Close the upload and delete the temporary file.

### Hosted foundation additions

The backend now has an explicit local-versus-hosted runtime split.

- `local` mode preserves the current local-first behavior.
- `hosted` mode enables hosted-only guardrails such as user ownership and API/worker separation.

In plain English: the analysis engine is still the same, but the service wrapper around it can now behave like a hosted app without forcing the local app to work that way too.

## HTTP Contract

### Shared Request Inputs
Expand Down
27 changes: 27 additions & 0 deletions apps/backend/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,21 @@ Override the port when needed:
SONIC_ANALYZER_PORT=8456 ./venv/bin/python server.py
```

Runtime profile and process role:

- `SONIC_ANALYZER_RUNTIME_PROFILE=local` keeps the current local-first behavior.
- `SONIC_ANALYZER_RUNTIME_PROFILE=hosted` turns on hosted-only guardrails such as required user identity headers on the run APIs.
- `SONIC_ANALYZER_PROCESS_ROLE=all` is the local default and starts the API plus in-process workers together.
- `SONIC_ANALYZER_PROCESS_ROLE=api` is the hosted default and starts the API without in-process workers.
- `SONIC_ANALYZER_PROCESS_ROLE=worker` is reserved for dedicated worker processes.

Hosted worker entry point:

```bash
cd apps/backend
SONIC_ANALYZER_RUNTIME_PROFILE=hosted SONIC_ANALYZER_PROCESS_ROLE=worker ./venv/bin/python worker.py
```

Current bind:

- host: `0.0.0.0`
Expand All @@ -183,6 +198,16 @@ Current CORS allow list:
- `http://localhost:5173`
- `http://127.0.0.1:5173`

Hosted auth hook:

- In hosted mode, canonical run endpoints require `X-ASA-User-Id`.
- In plain English: the backend now expects the hosted platform to tell ASA which signed-in user owns the run before it will create, fetch, interrupt, or delete that run.

Artifact storage boundary:

- Run artifacts are now written through `artifact_storage.py` instead of being created inline directly from every runtime call site.
- In plain English: the backend still stores files on local disk today, but the read/write boundary is now isolated so hosted object storage can replace it later without rewriting every analysis path.

## HTTP API

### `POST /api/analysis-runs/estimate`
Expand All @@ -201,6 +226,7 @@ Multipart form fields:
- `interpretation_mode` optional string
- `interpretation_profile` optional string
- `interpretation_model` optional string
- `X-ASA-User-Id` required in hosted mode

Response shape:

Expand Down Expand Up @@ -242,6 +268,7 @@ Multipart form fields:
- `track` required file upload
- `dsp_json_override` optional string, accepted but ignored
- `transcribe` optional boolean-like form value; when true the server appends `--transcribe`
- `X-ASA-User-Id` required in hosted mode

Query parameters:

Expand Down
Loading
Loading