Flare
Sign in Code now

For contributors

Flare is a Rust workspace: an Axum server, an executor worker, a language-server worker, PostgreSQL, and no frontend framework.

Run it locally

git clone https://github.com/Arthur-Kamau/Flare.git && cd Flare
cp .env.example .env     # set DATABASE_URL and the toolchain binds for your host
createdb flare
make dev                 # flare-server :3000, flare-executor, flare-lsp :3001

The executor needs bubblewrap and util-linux (or Docker). make test runs unit tests; make test-sandbox runs the hardening suite against real programs under bubblewrap and make test-sandbox-docker the same suite on the Docker backend (after make sandbox-images).

Add a language

One entry in crates/shared/src/languages.rs: pinned image, argv-only compile and run commands using {entry}, limits, a sample. The toolchain must exist in the image or on the worker host. Details in CLAUDE.md.

Add a language server

Install the server where the worker can see it, add a LanguageServer descriptor to the registry entry, restart flare-lsp and check /health.

Payments and plans

The four plans are rows in plans (migration 0009); change prices there. FLARE_PAYMENTS picks Pesapal (FLARE_PESAPAL_CONSUMER_KEY, _SECRET, sandbox by default; the IPN registers itself at /billing/webhook) or Stripe (FLARE_STRIPE_SECRET_KEY, _WEBHOOK_SECRET, FLARE_STRIPE_PRICE_<PLAN>, _YEAR and _SEAT, the per-extra-seat price whose quantity becomes subscriptions.extra_seats). Without keys /billing says so and make grant-collab EMAIL=… PLAN=teacher grants a plan by hand. FLARE_FX_USD_KES fixes the shilling rate (tests use 130); otherwise one keyless fetch a day. Entitlement and limits are computed only from stored rows (REQ-0005).

Collaboration worker

flare-collab (make collab, port 3002) holds one Yjs document per live project and talks the Yjs protocol to the browser. Its address (FLARE_COLLAB_URL, and FLARE_LSP_URL alike) reaches the page as given; when it names a loopback host and the page was opened on the other loopback name (localhost vs 127.0.0.1), the IDE swaps in the page's host, because the session cookie is scoped to a hostname and would otherwise never reach the room. It admits only signed-in owners and members (close codes 4401/4403/4404), drops viewers' writes, logs every accepted update to collab_updates and snapshots into project_files after two quiet seconds. Configure FLARE_COLLAB_* in .env; make test-db runs its socket test against your database.

Sign-in

Accounts come from Google or GitHub (OAuth) or an email and password (Argon2id hashes, /signup); sessions live server-side behind a cookie. Configure FLARE_BASE_URL and the client id/secret pairs in .env; /api/v1/me returns the signed-in user; /login?next=… is the sign-in page every Sign in link uses. Pages listed in MEMBER_DOCS (today: API) require sign-in.

Flare Desktop

apps/desktop is a Tauri app: its build.rs renders _ide.html and copies apps/web/static into dist/, so the desktop IDE is the web IDE with one bridge (shell/native.js): ide.js sends every /api/v1 call to the api command when window.__FLARE_NATIVE__ exists. The Rust side validates like the server, writes the files to a temporary folder and runs phases::execute with a builder that spawns the registry's argv directly (no isolation, on purpose; it never reaches crates/sandbox). make desktop runs it, make desktop-bundle builds installers (Linux needs WebKitGTK dev packages, see the CI workflow), and the Desktop GitHub workflow builds macOS. Publish by copying bundles into FLARE_DOWNLOADS_DIR (apps/web/downloads locally): /download lists them with size and SHA-256; nothing is listed for a platform without a file.

Execution off

FLARE_EXECUTION=off tells the API that no executor serves this database: POST /api/v1/executions answers 503 unavailable ("Running code is not available on this server yet") instead of queuing runs that would never start, and the IDE shows that message in the output pane. An empty FLARE_LSP_URL likewise switches the language-server client off. flare.koru.africa runs this way until the executor has its own machine; see infrastructure/deploy/README.md.

GitHub import and push

Uses the same GitHub OAuth app as sign-in (same callback) and needs FLARE_TOKEN_KEY, 64 hex characters (openssl rand -hex 32), which seals stored tokens (migration 0015, github_links). Changing the key makes stored tokens unreadable; users connect again. The server only ever calls api.github.com (REQ-0008).

Docs must follow features

make hooks installs a pre-commit check that refuses feature commits without a change to this site, README or CLAUDE.md.

The one rule

Never execute user code in the API process. Everything runs through the executor or language-server worker inside a sandbox. Requirements REQ-0001 and REQ-0002 in the repository carry the tests.