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:
David Montero Crespo 2026-05-14 17:06:27 -03:00
parent b4ab742456
commit 28d9cbc490
6 changed files with 85 additions and 117 deletions

View File

@ -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)

View File

@ -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 |
---

View File

@ -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

View File

@ -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"}

View File

@ -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

View File

@ -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