62 lines
2.8 KiB
Markdown
62 lines
2.8 KiB
Markdown
# Implementation Plan: M2 Market Web
|
|
|
|
**Branch**: `002-market-web` | **Date**: 2026-07-02 | **Spec**: [spec.md](./spec.md)
|
|
|
|
## Summary
|
|
|
|
One Coolify-deployed container: FastAPI backend that proxies the three live rails
|
|
(memory-api catalog, m2-ledger, Forgejo registry) with keys server-side, serving a
|
|
React/Vite SPA. Read-only + install handoff. Rides the proven CI/CD (push → deploy),
|
|
http-scheme domain market.machinemachine.ai.
|
|
|
|
## Technical Context
|
|
|
|
**Language**: Python 3.12 (FastAPI, httpx) + TypeScript React 18/Vite
|
|
**Storage**: none (stateless proxy; session cookie is signed, in-memory secret)
|
|
**Testing**: pytest for the backend proxy (httpx MockTransport per upstream, secrets-
|
|
leak test asserting no key strings in any response); vitest optional for components
|
|
**Deploy**: `web/Dockerfile` multi-stage (node build → python runtime), Coolify app
|
|
`m2-market-web`, env: FLEET_PASSCODE, SESSION_SECRET, MEMORY_API_URL/KEY,
|
|
LEDGER_URL/LEDGER_SERVICE_KEY, FORGEJO_URL/FORGEJO_TOKEN, REGISTRY_REPO
|
|
**Constraints**: constitution I (assembly: existing APIs only, no new rails), II (web is
|
|
a surface, never truth), IV (tenant filter server-side, same semantics as CLI reader), VI
|
|
(no secrets in image; runtime env)
|
|
|
|
## Constitution Check
|
|
|
|
Passes: no new services beyond the (sanctioned-as-surface) web app itself; all data
|
|
derived from registry/ledger/catalog; keys never leave the backend; read-only economy.
|
|
Deviation: none.
|
|
|
|
## Project Structure
|
|
|
|
```text
|
|
web/
|
|
├── backend/
|
|
│ ├── src/m2_market_web/
|
|
│ │ ├── main.py # FastAPI app: static serve + /api/* + /health
|
|
│ │ ├── auth.py # FLEET_PASSCODE login -> signed session cookie
|
|
│ │ ├── catalog.py # /api/search, /api/listing/{id} (memory-api proxy,
|
|
│ │ │ # tenant filter — mirror cli catalog.py semantics)
|
|
│ │ ├── ledger.py # /api/wallet/{op}, /api/economy (balances+audit links)
|
|
│ │ └── registry.py # /api/governance (open PRs+labels, listings+status)
|
|
│ ├── tests/
|
|
│ └── pyproject.toml # uv workspace member
|
|
├── frontend/ # Vite + React + TS, dark navy/cyan (mm brand)
|
|
│ ├── src/{pages,components,api.ts}
|
|
│ └── package.json
|
|
└── Dockerfile
|
|
```
|
|
|
|
## Sequencing
|
|
|
|
1. Backend proxy + tests [P with 2] → 2. Frontend SPA [P with 1] (against a typed
|
|
/api contract defined in contracts/web-api.md) → 3. Dockerfile + Coolify app + domain +
|
|
webhook → 4. Live verification vs SC-101..105.
|
|
|
|
## Contract
|
|
|
|
`contracts/web-api.md` (written with tasks): /api/login {passcode}; /api/search?q=&limit=;
|
|
/api/listing/{id}; /api/wallet/{operator}; /api/economy; /api/governance; /health.
|
|
Every /api/* except /health and /login requires the session cookie. Responses are
|
|
minimal DTOs — never raw upstream bodies (leak surface).
|