No description
  • Python 47.3%
  • Go 18.4%
  • TypeScript 14.3%
  • Svelte 13.4%
  • PHP 5%
  • Other 1.4%
Find a file
app-base ec09d380c6
Some checks failed
ci / backend (push) Has been cancelled
ci / frontend (push) Has been cancelled
ci / proxy (push) Has been cancelled
ci / whmcs (push) Has been cancelled
fix(provisioning): idempotent duplicate create (no 500 on unique-constraint race)
Catch the IntegrityError raised when a concurrent provision/create loses the
race on uq_services_provisioner_extservice, then re-fetch and return the
existing service idempotently (200) inside the transaction. The insert runs in
a SAVEPOINT so only the losing insert is rolled back, not the caller's unit of
work. Adds a real-MySQL race test asserting 200 (not 500) and no double
allocation.

task: D4 follow-up
2026-06-18 07:19:51 +00:00
.forgejo/workflows ci: add proxy (go test -race + cov gate + govulncheck) and whmcs jobs 2026-06-17 22:27:10 +00:00
backend fix(provisioning): idempotent duplicate create (no 500 on unique-constraint race) 2026-06-18 07:19:51 +00:00
deploy deploy: proxy node install script, env template, and deploy guide 2026-06-17 22:28:21 +00:00
docs fix(security): I4 review — CSRF-safe credential reveal + allocation-bound stats 2026-06-17 22:37:09 +00:00
frontend fix(security): I4 review — CSRF-safe credential reveal + allocation-bound stats 2026-06-17 22:37:09 +00:00
proxy ci: add proxy (go test -race + cov gate + govulncheck) and whmcs jobs 2026-06-17 22:27:10 +00:00
scripts chore: add seed script and fix MySQL 8.4 dev compose 2026-06-17 21:21:02 +00:00
whmcs-module feat(whmcs): provisioning server module for HTTP Proxy Panel 2026-06-17 22:24:16 +00:00
.env.example chore: scaffold app-base monorepo, CI skeleton, and dev infra 2026-06-17 20:56:31 +00:00
.gitignore chore: scaffold app-base monorepo, CI skeleton, and dev infra 2026-06-17 20:56:31 +00:00
README.md chore: scaffold app-base monorepo, CI skeleton, and dev infra 2026-06-17 20:56:31 +00:00

app-base

A reusable, runnable application starter repo: FastAPI + MySQL/MariaDB + Redis backend with a complete opaque-token auth system, and a SvelteKit static-SPA frontend with a custom Bootstrap theme. CI runs on Forgejo Actions with real MySQL + Redis service containers and coverage gates.

This repo is intentionally generic. A real application is created by forking it and layering domain logic on top; the base files are meant to be configured, not edited, so periodic git merge upstream/main stays clean.

This is Part 1 (app-base). It contains no domain logic.

Stack

Layer Tech
Backend Python 3.11+, FastAPI, SQLAlchemy 2.x, Alembic, Redis
Auth Single unified opaque bearer token (no JWT); header or cookie
Frontend SvelteKit + adapter-static (SPA), Bootstrap 5 + custom SCSS theme
CI Forgejo Actions (GitHub-Actions-compatible)
Dev infra docker-compose (MySQL + Redis), nginx (static + SPA fallback)

Layout

backend/    FastAPI app (app/core, app/models, app/schemas, app/api, app/services), alembic/, tests/
frontend/   SvelteKit static SPA (src/lib/{api,stores,components,ui,auth}, src/routes)
docs/       Generic contracts: security-spec, testing-spec, auth-contract, base-schema
deploy/     docker-compose.yml (mysql+redis), nginx.conf
.forgejo/   CI workflows
scripts/    seed / fixtures helpers

Quick start (development)

# 1. Secrets
cp .env.example .env          # then edit values (never commit .env)

# 2. Infra (MySQL + Redis)
docker compose -f deploy/docker-compose.yml up -d

# 3. Backend
cd backend
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
alembic upgrade head
python ../scripts/seed.py      # create a dev admin user
uvicorn app.main:app --reload  # http://localhost:8000  (docs at /docs in dev)

# 4. Frontend
cd ../frontend
npm install
npm run dev                    # http://localhost:5173

Auth model (summary)

  • One opaque, high-entropy token per session/key. Stored only as a SHA-256 hash (Redis for sessions, MySQL api_tokens for long-lived/named keys, with a Redis cache).
  • Resolved from either an Authorization: Bearer <token> header or an httpOnly+Secure+SameSite=Lax cookie holding the same token. One validation path.
  • Scopes: admin, provision, node, reserved client.
  • Cookie-authenticated state-changing requests require a double-submit X-CSRF-Token. Bearer-header requests are CSRF-exempt.
  • Instant revocation via Redis eviction / cache invalidation.

See docs/auth-contract.md and docs/security-spec.md for the full contract.

Testing

# Backend (needs MySQL + Redis reachable; see .env TEST_DATABASE_URL / REDIS_URL)
cd backend && pytest            # enforces >=90% coverage on app/services + app/api

# Frontend
cd frontend
npm run test:unit               # Vitest + Testing Library (coverage gate)
npm run test:e2e                # Playwright against the built SPA

CI runs all of the above on every push; see .forgejo/workflows/ci.yml.

License

Internal starter; license TBD.