Skip to content
Draft
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
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ that help readers decide what to do next without hunting.
| Evaluate quantum scaling | [research/QUANTUM_SCALING_STRATEGY.md](research/QUANTUM_SCALING_STRATEGY.md) | [technical/GRADIENT_OPTIMIZATION_POSTMORTEM.md](technical/GRADIENT_OPTIMIZATION_POSTMORTEM.md) |
| Audit implementation decisions | [technical/IMPLEMENTATION_NOTES.md](technical/IMPLEMENTATION_NOTES.md) | [technical/BENCHMARK.md](technical/BENCHMARK.md) |
| Deploy or host the platform | [LIGHTSAIL-DEPLOYMENT.md](LIGHTSAIL-DEPLOYMENT.md) | [START_HERE.md](START_HERE.md) |
| Find documents moved from the application repository | [repository/README.md](repository/README.md) | Original-path migration index |
| Review future direction | [FUTURE_ROADMAP.md](FUTURE_ROADMAP.md) | [future-roadmap/README.md](future-roadmap/README.md) |

## What is inside
Expand All @@ -30,6 +31,8 @@ that help readers decide what to do next without hunting.
- [design.md](design.md) - design rationale, cost model, and tradeoffs.
- [requirements.md](requirements.md) - functional and non-functional requirements.
- [AGENT_PROGRESS.md](AGENT_PROGRESS.md) - implementation and assistant progress notes.
- [repository/README.md](repository/README.md) - application repository documents, retaining their original folder structure.
- [superpowers/PRESENTATION_README.md](superpowers/PRESENTATION_README.md) - demo scripts, presentation material, and links to related design specs.

### Research

Expand Down Expand Up @@ -87,6 +90,7 @@ linking between documents in this repository.
| |-- QAOA_OPTIMIZATION_RESEARCH.md
| `-- BENCHMARK.md
|-- future-roadmap/
|-- repository/
`-- superpowers/
```

Expand Down
4 changes: 2 additions & 2 deletions START_HERE.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ Why we pivoted from speed tricks to scaling demonstration. Crossover predictions
Honest analysis: parameter-shift gradients were 2–3× slower. Root cause: 8× evaluation overhead.

### I want to deploy the platform
**→** [`../DEPLOYMENT-MANUAL.md`](../DEPLOYMENT-MANUAL.md) then [`LIGHTSAIL-DEPLOYMENT.md`](LIGHTSAIL-DEPLOYMENT.md)
**→** [`repository/DEPLOYMENT-MANUAL.md`](repository/DEPLOYMENT-MANUAL.md) then [`LIGHTSAIL-DEPLOYMENT.md`](LIGHTSAIL-DEPLOYMENT.md)

### I want to understand finance theory and the quantum use case
**→** [`FINANCIAL_MODELING_FOUNDATIONS.md`](FINANCIAL_MODELING_FOUNDATIONS.md)
Expand Down Expand Up @@ -133,7 +133,7 @@ docs/
| Understand quantum advantage | `research/QUANTUM_SCALING_STRATEGY.md` → `research/MATHEMATICAL_APPENDIX.md` §F |
| Understand system internals | `ARCHITECTURE.md` → `design.md` |
| Make product/advisor decisions | `research/QUANTUM_SCALING_STRATEGY.md` → `research/ALTERNATIVE_QUANTUM_FINANCE_PROBLEMS.md` |
| Deploy to production | `../DEPLOYMENT-MANUAL.md` → `LIGHTSAIL-DEPLOYMENT.md` |
| Deploy to production | `repository/DEPLOYMENT-MANUAL.md` → `LIGHTSAIL-DEPLOYMENT.md` |
| Take paid x402 requests on Algorand | `algorand-x402/algorand-x402-runbook.md` → `algorand-x402/algorand-x402-design.md` |
| Run or host Toju agent storage | `toju/toju-render-testnet-guide.md` → `toju/toju-devcon-demo.md` |

Expand Down
163 changes: 163 additions & 0 deletions guides/audit-cleanup-migration.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
# Audit cleanup: migration and release notes

This change set makes setup consistent across source checkouts, Python packages,
and Docker, and moves private storage operations behind authenticated server
routes. Existing installations need configuration and client updates before
upgrading. No database or account migration runs automatically.

Use the [environment guide](environment.md) for complete settings and the
[validation record](cleanup-validation.md) for checks performed and their limits.
`BREAKING` below means a confirmed change to existing behavior. Possible
regressions and unverified integrations are listed separately.

## Confirmed breaking changes

### BREAKING: storage credentials and permanent deletion

Rename these frontend settings and keep the new values on the server:

| Old variable | Replacement |
| --- | --- |
| `NEXT_PUBLIC_PINATA_JWT` | `PINATA_JWT` |
| `NEXT_PUBLIC_LIGHTHOUSE_KEY` | `LIGHTHOUSE_API_KEY` |

Pinata also accepts the server-only pair `PINATA_API_KEY` and `PINATA_API_SECRET`.
Remove the public names and rebuild the frontend. Rotate credentials that were
already shipped in browser bundles; renaming does not revoke them. Backend
research uploads need their own Pinata settings; `WEB3_STORAGE_API_KEY` is unused.

Vault uploads now require a signed-in session and run through server routes.
Permanent deletion requests (`hardDelete: true`) return HTTP 409 for an owned pin.
Normal removal changes only that user's vault tracking record. Use the provider
dashboard for permanent deletion after checking other users' dependencies on the
content. Existing `nft.storage` records remain supported as a Pinata alias.

### BREAKING: unified backend MongoDB routing

Agent, marketplace, proposal, and notification services now honor
`QB2_MONGODB_TARGET` and its selected `QB2_MONGODB_LOCAL_URI` or
`QB2_MONGODB_REMOTE_URI`, like the core API. They no longer always read the local
URI or independently default to `qds`. The shared default database is
`quantum_backend_v2`. Set `QB2_MONGODB_DATABASE` explicitly to your existing `qds`
or custom name before upgrading. If services previously used different servers
or databases, reconcile that split deliberately; changing settings does not move
records, wallets, or accounts.

Frontend auth remains separate: preserve `MONGODB_URI` and the effective auth
database. `MONGODB_DB_NAME` takes precedence over the newly supported legacy
fallback `MONGODB_DATABASE`; the default remains `quantum_platform`. A previously
ignored fallback value can now select a different database if the canonical name
is absent, so set the intended name explicitly.

### BREAKING: authenticated run, chat, and pharma access

Frontend run, legacy agent-chat, and pharma proxies now send the signed-in user's
identity. Legacy backend chat and pharma routes enforce authentication and
ownership; chat no longer uses a shared `default_user`. Anonymous callers and
callers reading another user's records must update their integration. Legacy
chat WebSockets also require authentication and session ownership.

Set the same server-only `AGENT_AUTH_BRIDGE_SECRET` of at least 32 characters on
both servers, and deploy matching frontend/backend code. Preserve the separate
`BETTER_AUTH_SECRET`. Old shared or unowned records are not automatically assigned
to a user. Keep `QB2_AUTH_REQUIRED=true` on shared deployments; the local bypass
and trial flag are not migration solutions.

### BREAKING: dependency extras and direct resource paths

The `dev` extra is removed. Use `uv sync --locked`; development dependencies are
installed through the default dependency group. Use `--no-dev` for production.
Chemistry dependencies now require `--extra pharma`; without them, molecular
submissions return HTTP 503 with installation guidance. Keep the extra on later
`uv run`/`uv sync` commands, or launch the installed environment with `make run`.
Docker chemistry builds require `--build-arg INSTALL_PHARMA=true`.

Python 3.12 or 3.13 is required; this was already the package requirement, even
though older README text advertised 3.11. Use the updated lockfile instead of
mixing pip changes into the uv environment. Broad prerelease allowance was
removed; required prerelease packages are pinned explicitly.

Prompt files moved from `backend/prompts/*.txt` to
`backend/src/quantum_backend_v2/prompts/`. Update scripts that read the old paths;
Python consumers can use `importlib.resources.files("quantum_backend_v2")`.
The unused `models.agent` module and browser pinning-provider implementations
were removed, so direct imports of those internal modules need review. Wheels
now include the required sibling packages, prompt assets, and Toju worker sources.
Toju still needs Node 22 and `npm ci` in its worker directory; Docker includes them.

### BREAKING: deployment and maintenance behavior

- Native startup consistently reads `backend/.env`; installed wheels read `.env`
in the launch directory. Exported variables win. Compose instead requires root
`.env` and passes it to the backend through `env_file`. Preserve effective values
when consolidating frontend settings into `.env.local`.
- Compose fixes the backend's internal bind to `0.0.0.0:8080`, publishes peer port
4011 from the backend, and fixes persistent runtime paths. Earlier env overrides
of those fields no longer apply. Set `API_DOMAIN` explicitly for deployment;
its default is now local. Frontend and MongoDB are still hosted separately.
- Kubo no longer starts with plain `docker compose up`; select `--profile storage`
or `--profile monitoring`. The default embedded worker count drops from six to
one. Set `QB2_LIBP2P_DEV_SERVICE_PEER_COUNT` if your setup needs the previous count.
- Backend and Caddy readiness checks now require MongoDB. A running Python process
alone no longer makes the deployment healthy.
- `make run-clean` refuses destructive cleanup. Use `make run`; back up and review
any deliberate peerstore or log removal separately. Startup also refuses busy
ports instead of killing their owners.
- Restart recovery marks interrupted jobs attributed to this coordinator as failed
and reconciles their reservations/credit holds. It does not resume computation
or change unowned legacy jobs. Use a unique, stable `QB2_PEER_ID` per coordinator.

### BREAKING: documentation paths and automatic guidance discovery

Forty-one Markdown documents moved into the `documentations` submodule; see the
[old-to-new path index](../repository/README.md). Initialize it with
`git submodule update --init documentations` after cloning or updating the parent
checkout. Update scripts and links that use the old paths. Frontend `AGENTS.md`
and `CLAUDE.md` are no longer discovered beside source files: load their
[new locations](../repository/README.md#frontend-guidance) explicitly in tools
that previously found them automatically.

## Potential regressions and validation limits

- Dependency and packaging changes may expose platform-specific chemistry or
external-consumer issues. Docker execution, native chemistry, real browser
IndexedDB, cloud storage, and wallet/payment integrations were not validated
end to end during this cleanup.
- Provider upload and MongoDB tracking writes are separate operations. If the
upload succeeds and the database write fails, provider-dashboard cleanup may be
needed. Pharma state remains process-local and is lost on restart.
- Source lint errors and the landing architecture test failure were fixed during
release checks. Existing lint warnings and optional/live test skips remain; see
the [validation record](cleanup-validation.md) for results and coverage limits.

A separate deployed sign-in outage was traced to database configuration and
network access. Its configuration-only redeployment did not include this change
set. That incident is not evidence of a regression from these changes, nor proof
that merging them repairs another deployment's database access. Auth error
handling was tested separately; full production account creation and sign-in
were not completed during the recorded checks.

## Rollout and rollback

1. Record the application commit, documentation submodule commit, deployed
artifacts, and effective configuration privately. Back up MongoDB and persistent
runtime volumes. Preserve database names, auth secrets, wallet encryption keys,
and coordinator IDs; do not replace existing env files with blank examples.
2. Apply the configuration changes above, install locked dependencies with the
extras you use, and rebuild the frontend. Test a staging deployment with
disposable data: readiness, sign-in, owned run/chat/pharma access, rejection of
unauthorized access, and each enabled storage or payment integration.
3. Drain active work before restarting. Deploy matching frontend and backend
versions, confirm the selected databases and expected records, then reopen
submissions. Check readiness, job failures, and credit reconciliation.
4. Commit documentation in its submodule before updating the parent pointer.
Describe confirmed breaks in commit/PR `BREAKING CHANGE:` notes, with migration
steps; list probable regressions and untested paths separately. This note does
not assign a release version or create a tag.

If rollback is needed, pause new writes and restore the matching application,
dependency lockfiles, deployment configuration, and documentation pointer. Review
jobs and credit changes made since rollout before restoring any database backup;
a code rollback does not undo them. Do not restore exposed provider credentials or
reopen public routes to make an older build work. If the older version requires
those behaviors, keep the affected feature unavailable until a safe fix is ready.
133 changes: 133 additions & 0 deletions guides/backend-features.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
# Backend feature reference

For installation and environment ownership, see [Environment setup](environment.md).

# Backend V2

`backend` is the next backend foundation for the decentralized quantum
service network. It starts with a thin FastAPI platform edge, explicit
configuration, typed models, and a protocol-first package layout that will
grow into the full migration plan described in `backend-migration.md`.

## Provenance

See [../repository/backend/PROVENANCE.md](../repository/backend/PROVENANCE.md) for the versioned canonical hashing and Merkle
proof format, backward-compatible bundle fields, and Ethereum anchoring handoff.

## Tokenized-stock portfolios

`GET /api/v1/finance/tokenized-assets` lists the Robinhood Stock Tokens whose Chainlink
price history can be analysed, with the sampling rules, data source and disclaimer.
`POST /api/v1/finance/tokenized-portfolio` takes `symbols`, `start_date`, `end_date` and
the usual optimizer settings, validates them, and queues a normal finance job (#18):

```json
{"symbols": ["AAPL", "MSFT", "SPY"], "start_date": "2026-06-23", "end_date": "2026-10-28"}
```

The job reads validated daily token prices from Robinhood Chain mainnet (read-only, see
[Robinhood Chain market data](../repository/backend/CHAIN_REGISTRY.md#robinhood-chain-market-data)) and runs the
existing portfolio optimizer on them. `GET /api/v1/finance/{job_id}` then adds:

- `market_data`: source, chain, block, aligned date range and per-asset token/feed
addresses and first/last round IDs.
- `allocation_weights`: the optimizer's equal weights over each method's selected assets.
- `disclaimer`: analysis only, not investment advice; nothing is signed or traded.
- `provenance`: the existing finance bundle, with every daily close as a Chainlink
oracle reference, so the exact inputs can be re-read by round ID.

Unsupported assets, future end dates, ranges without 60 weekdays and a `budget` the
optimizer would reject get a 422 before a job exists. Missing, invalid or insufficient
history (fewer than 60 aligned trading days) fails the job with a fixed message instead
of substituting prices. At most two history reads run at once per process, because the
default public RPC is rate-limited; `QB2_ROBINHOOD_MAINNET_RPC_URL` optionally
overrides it. Rounds are immutable, so caching them per feed is a possible follow-up.

## Kubo RPC client

`quantum_backend_v2.content.kubo.KuboClient` targets the pinned Kubo **v0.43.1**
service from #59/#60. Use it on the backend's **asyncio** loop, not inside the
libp2p Trio thread. It is optional: this change adds no startup probe, automatic
uploads, gateway reads or quantum-job integration.

Configuration flows through `AppSettings.from_env()` into `settings.kubo`:

| Variable | Default / purpose |
|---|---|
| `KUBO_RPC_URL` | `http://kubo:5001`; HTTP(S) root or `/api/v0` base |
| `KUBO_RPC_SECRET` | Private raw token shared with Kubo; required only when constructing the client |
| `KUBO_RPC_TIMEOUT_SECONDS` | `30`; finite I/O and total-operation timeout, maximum `300` |
| `KUBO_RPC_MAX_RESPONSE_BYTES` | `4194304`; decoded response budget, maximum 64 MiB |

The default hostname resolves inside Compose's `content_network`. Outside Docker,
use a protected connection; **do not publish RPC publicly**. URLs containing
credentials, query parameters or fragments are rejected. Redirects and environment
proxies are disabled; tokens are masked in settings and omitted from client errors.

```python
from quantum_backend_v2.config import KuboSettings
from quantum_backend_v2.content.kubo import KuboClient, KuboError


async def maybe_store(payload: bytes, config: KuboSettings) -> str | None:
try:
async with KuboClient(config) as client:
added = await client.add(payload)
return added.cid
except KuboError:
# Keep the original execution result; storage is optional.
return None
```

For repeated operations, reuse one client outside the loop. `async with`/`aclose()`
closes its HTTP session; binary input files remain caller-owned, but multipart
encoding may seek to their beginning and advance their cursor. Inputs may be
bytes or regular binary files; do not pass blocking pipes/custom blocking readers.

| Method | Typed result |
|---|---|
| `add(data, pin=True)` | CIDv1 and reported DAG size (not necessarily original file length) |
| `pin_add(cid, recursive=True)` / `pin_rm(cid, recursive=True)` | Acknowledged pin CIDs; unpinning is not immediate deletion |
| `pin_ls(cid=None)` | CID-to-pin metadata map; empty listings are valid; an indirect pin reports its pinned root in `through` |
| `dag_import(data, pin_roots=True)` | CAR block statistics and successfully pinned roots |
| `block_stat(cid)` | Reported CID and block size, not independent byte verification |

`KuboRejectedError` covers invalid client configuration/arguments, rejected HTTP
requests (including disallowed redirects) and explicit RPC/pin errors. Kubo sends
most command errors, such as an invalid CID or `pin_rm`/`pin_ls` on an unpinned
CID, as HTTP 500 with a JSON error body; a well-formed one with code 0 (normal),
1 (client) or 4 (forbidden) is rejected.
`KuboUnavailableError` covers timeouts/transport failures, HTTP 408/429/502-504,
any other HTTP 500 (implementation errors, rate limits, Kubo-internal context
timeouts, non-Kubo bodies) and invalid/incomplete responses. The total-operation
timeout includes upload time, so raise it for large inputs. Errors expose only
operation/category/status, never remote error text. Cancellation propagates.
**No automatic retries:** a failed or
timed-out mutation may already have stored blocks or changed pins; reconcile its
outcome rather than blindly replaying it. CAR import is not transactional, and
`pin_roots=False` returns no pinned roots, not an inventory of CAR header roots.

Kubo can put a late error in an HTTP trailer after status 200. The default
HTTP/1.1 transport uses public `httpcore`/`h11` interfaces to detect it before
returning a result; plain HTTPX otherwise drops these trailers. There is no
private monkeypatch or replacement TLS/parser stack. Use a direct endpoint or a
proxy that preserves trailers. Responses are read completely within the budget;
compressed responses are rejected, and raw server bodies/headers should not be logged.
See the pinned [RPC commands](https://github.com/ipfs/kubo/tree/v0.43.1/core/commands)
and [late-error emitter](https://github.com/ipfs/go-ipfs-cmds/blob/v0.16.1/http/responseemitter.go).

```bash
uv run --frozen pytest tests/unit/test_kubo*.py -q
```

MockTransport covers all six methods; local wire-level tests exercise actual
chunked HTTP trailers, fragmentation, pooling and privacy without external services.
An optional `tests/live/test_kubo_rpc.py` check is skipped unless
`QB2_KUBO_LIVE_TEST=1`. Run it **only against a disposable private node**, with its
URL/secret already provisioned in the environment; it creates harmless unique
fixtures and removes only their pins, never runs GC or deletes unrelated content.

```bash
# Only after provisioning the private disposable test URL/token in the environment:
QB2_KUBO_LIVE_TEST=1 uv run --frozen pytest tests/live/test_kubo_rpc.py -m live_kubo -q
```
Loading