chore(oss): drop dead auth/DB dependencies from OSS image
After Phase 4 of the OSS / pro split, the OSS code base imports zero auth/DB modules (verified with grep across backend/app/). But the requirements.txt + config.py + .env.example + docs still listed SQLAlchemy, aiosqlite, JWT/bcrypt, OAuth, SECRET_KEY etc. as if they were live. Self-hosters running `pip install -r requirements.txt` were pulling ~30 MB of packages the code never imports. Changes: * backend/requirements.txt — drop sqlalchemy, greenlet, aiosqlite, python-jose, passlib[bcrypt], bcrypt, authlib, email-validator, python-multipart. Keep fastapi, uvicorn, websockets, pydantic, pydantic-settings, httpx, mcp, esptool, wasmtime — everything OSS actually uses. * backend/app/core/config.py — Settings reduced to FRONTEND_URL only. Comment explains the overlay path that adds the rest at Docker build time. * backend/.env.example — same trim: only FRONTEND_URL, with a comment explaining why this file is almost empty. * README.md — "Auth & Project Persistence" section rewritten to describe .vlx export/import. Env-var table reduced to a single row. Stack table updated: no SQLAlchemy, no JWT, persistence = .vlx files. * CLAUDE.md — intro line updated (Auth: None, persistence: .vlx). Key-file-locations rewritten to list the OSS-stateless backend + the new lib/proRoutes / proSession / proSaveAction seams, with an explicit "removed in the split" note pointing to velxio-prod. Stores section drops useAuthStore (overlay-only now). Backend gotchas drop the bcrypt + email-validator + model-import notes. Implemented-features list replaces "Auth + URL persistence + user profile" with portable .vlx export/import. * docs/ESP32_EMULATION.md — two `docker run` examples dropped the `-e SECRET_KEY=...` arg (no longer needed). OSS build verified end-to-end (285 SEO pages prerender, 20 stateless routes, zero sqlalchemy imports). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b4ab742456
commit
28d9cbc490
57
CLAUDE.md
57
CLAUDE.md
|
|
@ -10,8 +10,11 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
|||
- Backend: FastAPI + Python for Arduino code compilation via arduino-cli
|
||||
- Simulation: Real AVR8 emulation using avr8js with full GPIO/timer/USART support
|
||||
- Components: Visual electronic components from wokwi-elements (LEDs, resistors, buttons, etc.)
|
||||
- Auth: Email/password + Google OAuth, JWT in httpOnly cookies
|
||||
- Project persistence: SQLite via SQLAlchemy 2.0 async + aiosqlite
|
||||
- Auth: None — OSS is single-user anonymous. Accounts + OAuth live in the
|
||||
velxio-prod private overlay that powers velxio.dev.
|
||||
- Project persistence: `.vlx` file export/import (`utils/vlxFile.ts`) —
|
||||
zero server-side state. Server-side persistence (SQLite or Postgres
|
||||
via SQLAlchemy) lives in the velxio-prod overlay.
|
||||
|
||||
The project uses **local clones of official Wokwi repositories** in `third-party/` instead of npm packages.
|
||||
|
||||
|
|
@ -167,8 +170,8 @@ The simulation runs at ~60 FPS using `requestAnimationFrame`:
|
|||
Main stores:
|
||||
- `useEditorStore`: Multi-file workspace (files[], activeFileId, openFileIds)
|
||||
- `useSimulatorStore`: Simulation state, components, wires, compiled hex, serialMonitorOpen
|
||||
- `useAuthStore`: Auth state (persisted in localStorage)
|
||||
- `useProjectStore`: Current project tracking
|
||||
- `useProjectStore`: Current loaded project metadata (id, slug, name) — used by the `.vlx` exporter to pick a download filename
|
||||
- `useAuthStore` (overlay-only) lives in `pro/frontend/src/pro/store/` in the velxio-prod repo. Pure OSS builds do not include it.
|
||||
|
||||
**6. Component-Pin Mapping**
|
||||
|
||||
|
|
@ -193,25 +196,35 @@ Wire positions auto-update when components move via `updateWirePositions()`.
|
|||
|
||||
## Key File Locations
|
||||
|
||||
### Backend
|
||||
- [backend/app/main.py](backend/app/main.py) - FastAPI app entry point, CORS config, model imports
|
||||
- [backend/app/api/routes/compile.py](backend/app/api/routes/compile.py) - Compilation endpoints (multi-file)
|
||||
- [backend/app/api/routes/auth.py](backend/app/api/routes/auth.py) - /api/auth/* endpoints
|
||||
- [backend/app/api/routes/projects.py](backend/app/api/routes/projects.py) - /api/projects/* + /api/user/*
|
||||
### Backend (OSS — stateless)
|
||||
- [backend/app/main.py](backend/app/main.py) - FastAPI app entry point, CORS, lifespan hooks
|
||||
- [backend/app/api/routes/compile.py](backend/app/api/routes/compile.py) - Compilation endpoints (multi-file, sync + async)
|
||||
- [backend/app/api/routes/compile_chip.py](backend/app/api/routes/compile_chip.py) - Custom-chip WASM compile
|
||||
- [backend/app/api/routes/libraries.py](backend/app/api/routes/libraries.py) - arduino-cli library search/install proxy
|
||||
- [backend/app/api/routes/simulation.py](backend/app/api/routes/simulation.py) - WebSocket bridge to QEMU workers
|
||||
- [backend/app/api/routes/iot_gateway.py](backend/app/api/routes/iot_gateway.py) - HTTP proxy for ESP32 web servers
|
||||
- [backend/app/services/arduino_cli.py](backend/app/services/arduino_cli.py) - arduino-cli wrapper
|
||||
- [backend/app/core/config.py](backend/app/core/config.py) - Settings (SECRET_KEY, DATABASE_URL `velxio.db`, GOOGLE_*)
|
||||
- [backend/app/core/security.py](backend/app/core/security.py) - JWT, password hashing
|
||||
- [backend/app/core/dependencies.py](backend/app/core/dependencies.py) - get_current_user, require_auth
|
||||
- [backend/app/database/session.py](backend/app/database/session.py) - async SQLAlchemy engine
|
||||
- [backend/app/models/user.py](backend/app/models/user.py) - User model
|
||||
- [backend/app/models/project.py](backend/app/models/project.py) - Project model (UniqueConstraint user_id+slug)
|
||||
- [backend/app/services/espidf_compiler.py](backend/app/services/espidf_compiler.py) - ESP-IDF compile wrapper
|
||||
- [backend/app/core/config.py](backend/app/core/config.py) - Minimal Settings (FRONTEND_URL only)
|
||||
- [backend/app/core/hooks.py](backend/app/core/hooks.py) - Extension hooks (record_compile, get_current_user_id, lifespan_startup) that the velxio-prod overlay fills in. OSS-default = no-op.
|
||||
|
||||
**Removed in the OSS/pro split (Phase 1-4):** auth.py, projects.py,
|
||||
admin.py, metrics.py, models/*, schemas/*, services/metrics.py,
|
||||
services/odoo_mail.py, services/project_files.py, database/session.py,
|
||||
core/dependencies.py, core/security.py, utils/{geo,slug,boards}.py. All
|
||||
of these live in [velxio-prod](https://github.com/velxio/velxio-prod)'s
|
||||
private overlay and are COPYed onto the image at Docker build time when
|
||||
deploying velxio.dev.
|
||||
|
||||
### Frontend - Core
|
||||
- [frontend/src/App.tsx](frontend/src/App.tsx) - Main app component, routing
|
||||
- [frontend/src/App.tsx](frontend/src/App.tsx) - Main app component, routing (with overlay route injection via `useProRoutes`)
|
||||
- [frontend/src/lib/proRoutes.ts](frontend/src/lib/proRoutes.ts) - Registry for routes the overlay registers at runtime
|
||||
- [frontend/src/lib/proSession.ts](frontend/src/lib/proSession.ts) - Optional session-check hook installed by the overlay
|
||||
- [frontend/src/lib/proSaveAction.ts](frontend/src/lib/proSaveAction.ts) - Save-button registry. Default = download `.vlx`; overlay overrides with SaveProjectModal.
|
||||
- [frontend/src/utils/vlxFile.ts](frontend/src/utils/vlxFile.ts) - Portable project export/import (no server needed)
|
||||
- [frontend/src/store/useEditorStore.ts](frontend/src/store/useEditorStore.ts) - Multi-file workspace state
|
||||
- [frontend/src/store/useSimulatorStore.ts](frontend/src/store/useSimulatorStore.ts) - Simulation state, components, wires
|
||||
- [frontend/src/store/useAuthStore.ts](frontend/src/store/useAuthStore.ts) - Auth state (localStorage)
|
||||
- [frontend/src/store/useProjectStore.ts](frontend/src/store/useProjectStore.ts) - Current project
|
||||
- [frontend/src/store/useProjectStore.ts](frontend/src/store/useProjectStore.ts) - Current loaded project metadata
|
||||
|
||||
### Frontend - Editor UI
|
||||
- [frontend/src/components/editor/CodeEditor.tsx](frontend/src/components/editor/CodeEditor.tsx) - Monaco editor (key={activeFileId} for per-file undo history)
|
||||
|
|
@ -409,9 +422,6 @@ metadata staleness check), not the other two.
|
|||
|
||||
### 9. Backend Gotchas
|
||||
|
||||
- **bcrypt**: Pin `bcrypt==4.0.1` — bcrypt 5.x breaks passlib 1.7.4
|
||||
- **email-validator**: Must be installed separately (`pip install email-validator`)
|
||||
- **Model imports**: Both `app.models.user` and `app.models.project` must be imported before DB init (done in `main.py`)
|
||||
- **RP2040 board manager**: arduino-cli needs the earlephilhower URL before `rp2040:rp2040` install:
|
||||
```
|
||||
arduino-cli config add board_manager.additional_urls \
|
||||
|
|
@ -486,11 +496,10 @@ Enable verbose logging:
|
|||
- ILI9341 TFT display simulation
|
||||
- Library Manager (install/search arduino libraries)
|
||||
- Example projects gallery
|
||||
- **Auth**: email/password + Google OAuth, JWT httpOnly cookies
|
||||
- **Project persistence**: create/read/update/delete with URL slugs (`/:username/:slug`)
|
||||
- **User profile page** at `/:username`
|
||||
- **Portable project persistence**: `.vlx` file export/import — single-file JSON snapshot of the whole workspace, no server, no DB
|
||||
- **Resizable file explorer** panel (drag handle, collapse toggle)
|
||||
- Docker standalone image published to GHCR + Docker Hub
|
||||
- **OSS / pro split**: auth, accounts, public profiles, admin panel, server-side project URLs and analytics live in the private [velxio-prod](https://github.com/velxio/velxio-prod) overlay that runs velxio.dev. OSS is single-user, anonymous, fully self-hostable.
|
||||
|
||||
**In Progress:**
|
||||
- Functional wire connections (electrical signal routing)
|
||||
|
|
|
|||
41
README.md
41
README.md
|
|
@ -237,13 +237,19 @@ See [docs/RASPBERRYPI3_EMULATION.md](docs/RASPBERRYPI3_EMULATION.md) for full te
|
|||
- Browse and install the full Arduino library index directly from the UI
|
||||
- Live search, installed tab, version display
|
||||
|
||||
### Auth & Project Persistence
|
||||
### Portable Project Persistence
|
||||
|
||||
- **Email/password** and **Google OAuth** sign-in
|
||||
- **Project save** with name, description, and public/private visibility
|
||||
- **Project URL** — each project gets a permanent URL at `/project/:id`
|
||||
- **Sketch files stored on disk** per project (accessible from the host via Docker volume)
|
||||
- **User profile** at `/:username` showing public projects
|
||||
- **`.vlx` file format** — single-file JSON snapshot of the whole
|
||||
workspace (boards, file groups, components, wires). Download with the
|
||||
Save button, restore with the Open `.vlx` button. The format is
|
||||
versioned so files round-trip cleanly across versions.
|
||||
- **Zero server-side state** — OSS Velxio has no database, no accounts,
|
||||
no login. Your projects live wherever you keep your `.vlx` files
|
||||
(local disk, Dropbox, GitHub, Google Drive — your choice).
|
||||
- Need accounts, public profiles at `/:username`, server-side project
|
||||
URLs and admin panels? Those live in the private overlay used to run
|
||||
velxio.dev — see [velxio-prod](https://github.com/velxio/velxio-prod)
|
||||
for the open-core split details.
|
||||
|
||||
### Example Projects
|
||||
|
||||
|
|
@ -329,20 +335,13 @@ required** to get going.
|
|||
|
||||
#### Optional: customize environment
|
||||
|
||||
Create `backend/.env` (copy from `backend/.env.example`) only when you need
|
||||
OAuth, a fixed `SECRET_KEY`, or HTTPS-only cookies. The compose file picks
|
||||
it up automatically if it exists.
|
||||
The OSS image has almost no configuration — there's no database, no auth,
|
||||
no third-party integrations. Create `backend/.env` only if you want to
|
||||
change the CORS origin used during local development.
|
||||
|
||||
| Variable | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `SECRET_KEY` | *(auto-generated)* | JWT signing secret. If unset the entrypoint creates one and saves it under `data/.secret_key`. |
|
||||
| `DATABASE_URL` | `sqlite+aiosqlite:////app/data/velxio.db` | SQLite path |
|
||||
| `DATA_DIR` | `/app/data` | Directory for project files |
|
||||
| `FRONTEND_URL` | `http://localhost:5173` | Used for OAuth redirect |
|
||||
| `GOOGLE_CLIENT_ID` | — | Google OAuth client ID |
|
||||
| `GOOGLE_CLIENT_SECRET` | — | Google OAuth client secret |
|
||||
| `GOOGLE_REDIRECT_URI` | `http://localhost:8001/api/auth/google/callback` | Must match Google Console |
|
||||
| `COOKIE_SECURE` | `false` | Set `true` when serving over HTTPS |
|
||||
| `FRONTEND_URL` | `http://localhost:5173` | Origin allowed by CORS for local Vite dev |
|
||||
|
||||
> **Deploying behind a reverse proxy?** The container listens on plain HTTP
|
||||
> on port 80 and accepts any `Host` header — no `server_name` whitelist.
|
||||
|
|
@ -451,16 +450,16 @@ velxio/
|
|||
| Layer | Stack |
|
||||
| --- | --- |
|
||||
| Frontend | React 19, Vite 7, TypeScript 5.9, Monaco Editor, Zustand, React Router 7 |
|
||||
| Backend | FastAPI, SQLAlchemy 2.0 async, aiosqlite, uvicorn |
|
||||
| Backend | FastAPI, uvicorn (stateless: compile, libraries, simulation, MCP) |
|
||||
| AVR Simulation | avr8js (ATmega328p / ATmega2560) |
|
||||
| RP2040 Simulation | rp2040js (ARM Cortex-M0+) |
|
||||
| RISC-V Simulation | RiscVCore.ts (RV32IMC, custom TypeScript) |
|
||||
| ESP32 Simulation | QEMU 8.1.3 lcgamboa fork (Xtensa LX6/LX7) |
|
||||
| Raspberry Pi 3 Simulation | QEMU 8.1.3 (`qemu-system-aarch64 -M raspi3b`) + Raspberry Pi OS Trixie |
|
||||
| UI Components | wokwi-elements (Web Components) |
|
||||
| Compiler | arduino-cli (subprocess) |
|
||||
| Auth | JWT (httpOnly cookie), Google OAuth 2.0 |
|
||||
| Persistence | SQLite + disk volume (`/app/data/projects/{id}/`) |
|
||||
| Compiler | arduino-cli (subprocess) + ESP-IDF (subprocess) |
|
||||
| Auth | None — anonymous, single-user editor by design |
|
||||
| Persistence | `.vlx` file export/import (no server-side database) |
|
||||
| Deploy | Docker, nginx, GitHub Actions → GHCR + Docker Hub |
|
||||
|
||||
---
|
||||
|
|
|
|||
|
|
@ -1,26 +1,10 @@
|
|||
# Velxio backend environment variables
|
||||
# Copy this file to backend/.env and edit as needed.
|
||||
# Velxio OSS backend environment variables.
|
||||
# The OSS image has no auth, no database, no third-party integrations —
|
||||
# this file is almost empty for a reason. Copy to backend/.env only if
|
||||
# you actually need to change a setting.
|
||||
|
||||
# JWT signing secret — REQUIRED. Use a long random string in production.
|
||||
SECRET_KEY=change-me-in-production-use-a-long-random-string
|
||||
|
||||
# SQLite database path (async driver).
|
||||
# Docker default points at the /app/data volume.
|
||||
DATABASE_URL=sqlite+aiosqlite:////app/data/velxio.db
|
||||
|
||||
# Directory where per-project sketch files are stored.
|
||||
DATA_DIR=/app/data
|
||||
|
||||
# Frontend URL — used for OAuth redirects and CORS.
|
||||
# CORS origin allowed during local Vite development. The Docker image
|
||||
# accepts any Host header, so this only matters when running the
|
||||
# backend on its own (uvicorn) and the frontend on a separate dev
|
||||
# server. Production deployments use a host nginx reverse proxy instead.
|
||||
FRONTEND_URL=http://localhost:5173
|
||||
|
||||
# Google OAuth credentials (leave empty to disable Google login).
|
||||
GOOGLE_CLIENT_ID=
|
||||
GOOGLE_CLIENT_SECRET=
|
||||
GOOGLE_REDIRECT_URI=http://localhost:8001/api/auth/google/callback
|
||||
|
||||
# Set to true when serving over HTTPS (controls Secure flag on JWT cookie).
|
||||
COOKIE_SECURE=false
|
||||
|
||||
# JWT access token lifetime in minutes (default: 7 days).
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES=10080
|
||||
|
|
|
|||
|
|
@ -2,39 +2,23 @@ from pydantic_settings import BaseSettings
|
|||
|
||||
|
||||
class Settings(BaseSettings):
|
||||
SECRET_KEY: str = "change-me-in-production-use-a-long-random-string"
|
||||
DATABASE_URL: str = "sqlite+aiosqlite:///./velxio.db"
|
||||
DATA_DIR: str = "."
|
||||
GOOGLE_CLIENT_ID: str = ""
|
||||
GOOGLE_CLIENT_SECRET: str = ""
|
||||
GOOGLE_REDIRECT_URI: str = "http://localhost:8001/api/auth/google/callback"
|
||||
"""OSS settings — stateless deployment.
|
||||
|
||||
Auth, DB, OAuth, billing, mail relay etc. moved to the velxio-prod
|
||||
private overlay during the Phase 1-4 OSS/pro split. The overlay
|
||||
physically replaces this file at Docker build time with a richer
|
||||
Settings class that ADDS those fields on top of FRONTEND_URL (see
|
||||
pro/backend/app/core/config.py).
|
||||
|
||||
Adding a setting here means the stateless OSS image will read it.
|
||||
If the new setting only makes sense with an auth/DB stack (e.g.
|
||||
SMTP creds, third-party API keys for analytics), add it to the
|
||||
overlay's config.py instead so the OSS image stays minimal.
|
||||
"""
|
||||
|
||||
# CORS — used by main.py to whitelist the SPA origin during local dev
|
||||
# and to build redirect URLs from auth routes in the overlay.
|
||||
FRONTEND_URL: str = "http://localhost:5173"
|
||||
# Set to true in production (HTTPS). Controls the Secure flag on the JWT cookie.
|
||||
COOKIE_SECURE: bool = False
|
||||
ACCESS_TOKEN_EXPIRE_MINUTES: int = 10080 # 7 days
|
||||
|
||||
# ── Odoo transactional-mail relay ──────────────────────────────────────
|
||||
# The Velxio backend POSTs to `<ODOO_URL>/velxio/api/send-welcome` and
|
||||
# `<ODOO_URL>/velxio/api/send-password-reset` on register / forgot-
|
||||
# password. Calls are fire-and-forget — registration succeeds even when
|
||||
# ODOO_URL is empty (no mail will be sent), so dev / CI doesn't need a
|
||||
# working Odoo instance.
|
||||
#
|
||||
# ODOO_API_KEY must match the company-level X-Velxio-API-Key stored in
|
||||
# `res.company.velxio_api_key` on the Odoo side (see
|
||||
# odoo-addons/velxio_subscription/controllers/api.py).
|
||||
ODOO_URL: str = ""
|
||||
ODOO_API_KEY: str = ""
|
||||
# How long to wait for Odoo before giving up the fire-and-forget call.
|
||||
# Kept short so a stalled Odoo never holds an asyncio.create_task open
|
||||
# for minutes.
|
||||
ODOO_MAIL_TIMEOUT_S: float = 10.0
|
||||
|
||||
# Password-reset tuning. Tokens are random 32-byte URL-safe strings;
|
||||
# only the SHA-256 hash is persisted so a database leak doesn't reveal
|
||||
# usable reset codes.
|
||||
PASSWORD_RESET_TOKEN_TTL_MINUTES: int = 60
|
||||
PASSWORD_RESET_RATE_LIMIT_PER_HOUR: int = 3
|
||||
|
||||
model_config = {"env_file": ".env", "env_file_encoding": "utf-8"}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,21 +1,14 @@
|
|||
# Velxio OSS backend — stateless: compile, libraries, simulation,
|
||||
# iot_gateway, MCP. No auth, no DB, no project persistence; those live in
|
||||
# the velxio-prod private overlay's pro/backend/requirements.txt and are
|
||||
# pip-installed on top of this list at Docker build time.
|
||||
fastapi==0.115.0
|
||||
uvicorn[standard]==0.32.0
|
||||
websockets>=12.0
|
||||
sqlalchemy==2.0.36
|
||||
# greenlet is needed by SQLAlchemy async on some Python builds (notably Windows
|
||||
# Python 3.12+ wheels). Without it, app startup fails with
|
||||
# "ValueError: the greenlet library is required". See issue #120.
|
||||
greenlet>=3.0.0
|
||||
aiosqlite==0.20.0
|
||||
pydantic>=2.11.0
|
||||
pydantic-settings>=2.6.0
|
||||
python-multipart==0.0.12
|
||||
python-jose[cryptography]==3.3.0
|
||||
passlib[bcrypt]==1.7.4
|
||||
bcrypt==4.0.1
|
||||
# httpx — iot_gateway proxy + MCP
|
||||
httpx>=0.27.1
|
||||
authlib==1.3.1
|
||||
email-validator==2.2.0
|
||||
mcp>=1.0.0
|
||||
esptool>=4.7.0
|
||||
# WASM runtime for Custom Chips on ESP32 (chip's WASM runs in the QEMU worker
|
||||
|
|
|
|||
|
|
@ -251,11 +251,10 @@ docker run -d \
|
|||
--name velxio \
|
||||
-p 3080:80 \
|
||||
-v $(pwd)/data:/app/data \
|
||||
-e SECRET_KEY=your-secret \
|
||||
ghcr.io/davidmonterocrespo24/velxio:master
|
||||
```
|
||||
|
||||
ESP32 emulation with full GPIO is active automatically. No additional environment variables are needed.
|
||||
ESP32 emulation with full GPIO is active automatically. No environment variables are needed (the OSS image is stateless — no auth, no DB).
|
||||
|
||||
### 2.2 Local Image Build
|
||||
|
||||
|
|
@ -263,7 +262,7 @@ ESP32 emulation with full GPIO is active automatically. No additional environmen
|
|||
git clone https://github.com/davidmonterocrespo24/velxio.git
|
||||
cd velxio
|
||||
docker build -f Dockerfile.standalone -t velxio .
|
||||
docker run -d -p 3080:80 -e SECRET_KEY=secret velxio
|
||||
docker run -d -p 3080:80 velxio
|
||||
```
|
||||
|
||||
> **Build time note:** QEMU compilation takes 15-30 minutes the first time.
|
||||
|
|
@ -1108,7 +1107,7 @@ The connection logic lives in `SimulatorCanvas.tsx`: it detects the tag of the w
|
|||
|
||||
```bash
|
||||
# Docker — fully automatic, no extra variables needed:
|
||||
docker run -d -p 3080:80 -e SECRET_KEY=secret ghcr.io/davidmonterocrespo24/velxio:master
|
||||
docker run -d -p 3080:80 ghcr.io/davidmonterocrespo24/velxio:master
|
||||
|
||||
# Windows with lib (full emulation: GPIO + WiFi + ADC + I2C + SPI + RMT + LEDC):
|
||||
cd backend && venv\Scripts\activate
|
||||
|
|
|
|||
Loading…
Reference in New Issue