{"id":50731890,"url":"https://github.com/abskrj/velane","last_synced_at":"2026-06-10T09:31:04.578Z","repository":{"id":360792356,"uuid":"1251723283","full_name":"abskrj/velane","owner":"abskrj","description":"Code Runtime and iPaaS for AI Agent  — execute Bun/Python snippets at scale via POST API + integrate with 800+ tools (N8N for AI Agents)","archived":false,"fork":false,"pushed_at":"2026-06-07T21:26:47.000Z","size":1018,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T23:19:32.908Z","etag":null,"topics":["agentic-workflows-orchestration","ai-agent","ai-agent-runtime","ipaas","sandbox","workflow-orchestration"],"latest_commit_sha":null,"homepage":"https://docs.velane.sh","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/abskrj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-27T21:19:08.000Z","updated_at":"2026-06-07T21:26:41.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/abskrj/velane","commit_stats":null,"previous_names":["abskrj/runeforge","abskrj/velane"],"tags_count":9,"template":false,"template_full_name":null,"purl":"pkg:github/abskrj/velane","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abskrj%2Fvelane","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abskrj%2Fvelane/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abskrj%2Fvelane/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abskrj%2Fvelane/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/abskrj","download_url":"https://codeload.github.com/abskrj/velane/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/abskrj%2Fvelane/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34146871,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["agentic-workflows-orchestration","ai-agent","ai-agent-runtime","ipaas","sandbox","workflow-orchestration"],"created_at":"2026-06-10T09:31:00.012Z","updated_at":"2026-06-10T09:31:03.456Z","avatar_url":"https://github.com/abskrj.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Velane\n\n**AI Agent Code Runtime** — write Bun or Python snippets, expose them as POST APIs, connect to 800+ integrations, and run at scale in secure sandboxed runtimes.\n\nVelane is an open-source, multi-tenant platform that lets AI agents deploy code snippets as callable HTTP endpoints — with versioning, secrets injection, canary traffic splitting, streaming, an admin dashboard, native MCP integration for Cursor and Claude Code, and **built-in OAuth connections to over 800 third-party services** (Salesforce, GitHub, Slack, HubSpot, Stripe, Notion, Linear, and hundreds more).\n\n---\n\n## Features\n\n- **800+ integrations** — connect Salesforce, GitHub, Slack, HubSpot, Stripe, Notion, Linear, Zendesk, Airtable, and hundreds more via OAuth. Snippet code calls any provider's native API through a unified `integration()` client — no credentials in code, no SDK installs\n- **Snippet runtime** — execute Bun (TypeScript) or Python snippets via `POST /v1/invoke/{snippet}`\n- **Sync, async, and streaming** — synchronous blocking, background async with webhook callbacks, and `text/event-stream` streaming\n- **Three environments** — `dev` → `staging` → `prod` promotion flow\n- **Versioned deployments** — each publish creates an immutable version; instant rollback to any prior version\n- **Canary traffic splitting** — send X% of prod traffic to a new version while the rest hits stable\n- **Secrets injection** — AES-256-GCM encrypted key-value pairs injected as env vars at invocation time; values never returned by the API\n- **Egress policy** — per-tenant IP/CIDR and domain blocklist enforced inside the executor\n- **Observability** — per-invocation logs (S3/MinIO), metrics (ClickHouse), and invocation replay\n- **Admin portal** — self-serve dashboard for snippet editing, API key management, team invites, branding, usage, and egress config\n- **Embeddable dashboard** — iframe-safe read-only snippet browser with white-label theming\n- **MCP server** — connect Cursor or Claude Code directly to Velane to generate and deploy snippets without leaving your IDE\n- **Git push-to-deploy** — connect a GitHub repo; push to `main` → staging, tag `v*` → prod\n- **JWT auth** — RS256 access tokens (15 min) + refresh tokens; JWKS endpoint for third-party verification\n- **Firecracker executor** — optional VM-boundary isolation via AWS Firecracker (requires KVM; enabled with `EXECUTOR_TYPE=firecracker`)\n- **Seccomp profiles** — syscall allowlist applied to executor containers in production\n\n---\n\n## 800+ Integrations\n\nVelane connects to any OAuth-supported service through a built-in proxy — your snippet code never handles tokens directly.\n\n```typescript\n// Bun — works the same way for all 800+ providers\nimport { integration } from '@velane/integrations'\n\nconst gh     = integration('github')\nconst sf     = integration('salesforce')\nconst slack  = integration('slack')\n\n// GitHub — list repos\nconst repos = await gh.get('/user/repos')\n\n// Salesforce — create a case\nconst newCase = await sf.post('/services/data/v60.0/sobjects/Case', {\n  Subject: 'Login issue',\n  Status:  'New',\n})\n\n// Slack — post a message\nawait slack.post('/chat.postMessage', {\n  channel: '#alerts',\n  text:    `Case created: ${newCase.id}`,\n})\n```\n\n```python\n# Python — identical pattern\nfrom velane.integrations import integration\n\ngh    = integration(\"github\")\nrepos = gh.get(\"/user/repos\")\n```\n\n**Setup:** Go to **Integrations** in the admin portal, click **Configure** on any provider to enter your OAuth app credentials, then click **Connect** to complete the OAuth flow. No SDK installs, no credential management in snippet code.\n\nSupported categories include CRM, ticketing, project management, communication, payments, storage, marketing, analytics, developer tools, and more. Full provider list at [nango.dev/integrations](https://www.nango.dev/integrations).\n\n---\n\n## Architecture\n\n```\n┌──────────────────────────────────────────────────────────┐\n│                        Clients                           │\n│   Admin Portal  ·  Embed Dashboard  ·  CLI  ·  MCP       │\n└───────────────────────────┬──────────────────────────────┘\n                            │\n┌───────────────────────────▼──────────────────────────────┐\n│                Control Plane (Go)                        │\n│   chi router · pgx/v5 · JWT auth · API key auth          │\n│   Scheduler · Async Worker · Observability Pipeline      │\n│   OAuth Proxy (800+ providers via Nango)                 │\n└──────┬────────────────────┬────────────────┬─────────────┘\n       │                    │                │\n  ┌────▼────┐        ┌──────▼─────┐   ┌──────▼─────┐\n  │Postgres │        │   Redis    │   │ClickHouse  │\n  │ (state) │        │(queue +    │   │ (metrics)  │\n  └─────────┘        │ warm pool) │   └────────────┘\n                     └──────┬─────┘\n                            │\n          ┌─────────────────▼─────────────────┐\n          │           Executor Pool            │\n          │  ┌──────────┐   ┌──────────────┐  │\n          │  │   Bun    │   │    Python    │  │\n          │  │  :8081   │   │    :8082     │  │\n          │  └──────────┘   └──────────────┘  │\n          └───────────────────────────────────┘\n```\n\n---\n\n## Quickstart\n\n### Prerequisites\n\n- [Docker](https://docs.docker.com/get-docker/) + Docker Compose\n- Node.js 24 LTS (24.16.0 recommended) and npm (frontend dev only)\n- Go 1.26.3+ (CLI or control plane dev only)\n\n### 1. Clone and configure\n\n```bash\ngit clone https://github.com/abskrj/velane.git\ncd velane\n```\n\nOpen `docker-compose.yml` and uncomment the bootstrap vars to seed your first admin user:\n\n```yaml\n# services \u003e control-plane \u003e environment\nBOOTSTRAP_EMAIL: admin@example.com\nBOOTSTRAP_PASSWORD: changeme123\nBOOTSTRAP_TENANT: myorg\n```\n\n### 2. Start everything\n\n```bash\ndocker compose up --build\n```\n\nAll services start, database migrations run automatically, and the admin user + tenant are created on first boot. Once `control-plane` logs `http server listening`, you're ready.\n\n### 3. Open the UIs\n\n| Interface | URL | Description |\n|-----------|-----|-------------|\n| **Admin portal** | http://localhost:8092 | Snippet editor, integrations, team, branding, usage |\n| **Embed dashboard** | http://localhost:8091 | Read-only iframe snippet viewer |\n| API | http://localhost:8080 | REST API |\n| MCP server | http://localhost:8090 | Cursor / Claude Code integration |\n| MinIO console | http://localhost:9001 | Log storage (minioadmin / minioadmin) |\n\nLog into the admin portal at http://localhost:8092 with the credentials from the bootstrap step.\n\n---\n\n## Writing your first snippet\n\n### Via the admin portal\n\n1. Open http://localhost:8092 and log in\n2. Go to **Snippets → New Snippet**\n3. Name it, pick a language (Bun or Python), write your code in the Monaco editor\n4. Click **Publish → dev**\n5. Use the **Test** panel to invoke it inline\n\n### Via the API\n\n```bash\nKEY=vl_xxxx   # your API key\n\n# Create a snippet\nSNIPPET=$(curl -s -X POST http://localhost:8080/v1/snippets \\\n  -H \"Authorization: Bearer $KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"hello\",\"language\":\"bun\"}' | jq -r .id)\n\n# Push code as a new version\nVER=$(curl -s -X POST http://localhost:8080/v1/snippets/$SNIPPET/versions \\\n  -H \"Authorization: Bearer $KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"code\":\"export default async (req) =\u003e ({ hello: req.name })\"}' | jq -r .version_number)\n\n# Publish to dev\ncurl -s -X POST \"http://localhost:8080/v1/snippets/$SNIPPET/versions/$VER/publish?env=dev\" \\\n  -H \"Authorization: Bearer $KEY\"\n\n# Invoke it\ncurl -s -X POST http://localhost:8080/v1/invoke/$SNIPPET \\\n  -H \"Authorization: Bearer $KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"name\":\"world\"}' | jq\n# → { \"hello\": \"world\" }\n```\n\n### Via the CLI\n\n```bash\ncd services/cli \u0026\u0026 go build -o velane .\n\n./velane login --key vl_xxxx --tenant myorg --api-url http://localhost:8080\n./velane snippets push handler.ts --publish dev\n./velane invoke \u003csnippet-id\u003e --input '{\"name\":\"world\"}'\n./velane invoke \u003csnippet-id\u003e --stream   # SSE streaming\n```\n\n---\n\n## Connecting an integration\n\n1. In the admin portal, go to **Integrations**\n2. Find a provider (e.g. Salesforce) and click **Configure**\n3. The modal shows the **OAuth redirect URL** to register in your OAuth app settings — copy it\n4. Create an OAuth app in the provider's developer console and paste the client ID / secret back\n5. Click **Save**, then **Connect** to complete the OAuth flow\n6. In snippet code, use `integration('salesforce')` — tokens are injected automatically\n\n```typescript\nimport { integration } from '@velane/integrations'\n\nexport default async function handler(input: { caseId: string }) {\n  const sf = integration('salesforce')\n  return await sf.get(`/services/data/v60.0/sobjects/Case/${input.caseId}`)\n}\n```\n\n---\n\n## Invocation modes\n\n```bash\n# Synchronous (default) — blocks until result\ncurl -X POST http://localhost:8080/v1/invoke/$SNIPPET \\\n  -H \"Authorization: Bearer $KEY\" -d '{\"name\":\"world\"}'\n\n# Async — returns 202 immediately, fires webhook on completion\ncurl -X POST http://localhost:8080/v1/invoke/$SNIPPET \\\n  -H \"Authorization: Bearer $KEY\" \\\n  -H \"X-Invoke-Mode: async\" \\\n  -d '{\"name\":\"world\",\"callback_url\":\"https://yourserver.com/webhook\"}'\n\n# Streaming — text/event-stream\ncurl -X POST http://localhost:8080/v1/invoke/$SNIPPET \\\n  -H \"Authorization: Bearer $KEY\" \\\n  -H \"X-Invoke-Mode: stream\" \\\n  -d '{}'\n\n# Pinned version\ncurl -X POST \"http://localhost:8080/v1/invoke/$SNIPPET?version=v2\" \\\n  -H \"Authorization: Bearer $KEY\" -d '{}'\n```\n\n---\n\n## MCP Integration (Cursor / Claude Code)\n\nAdd to `.cursor/mcp.json` or `~/.claude/mcp.json`:\n\n```json\n{\n  \"mcpServers\": {\n    \"velane\": {\n      \"url\": \"http://localhost:8090/mcp\",\n      \"headers\": { \"Authorization\": \"Bearer vl_xxxx\" }\n    }\n  }\n}\n```\n\nAvailable tools: `list_snippets`, `get_snippet`, `create_snippet`, `update_draft`, `publish_snippet`, `invoke_snippet`, `get_logs`, `list_secrets`, `set_secret`, `get_metrics`, `list_connections`, `get_integration_docs`.\n\n---\n\n## Embeddable Dashboard\n\nIssue a short-lived embed token and drop it into any page:\n\n```bash\nTOKEN=$(curl -s -X POST http://localhost:8080/v1/embed/tokens \\\n  -H \"Authorization: Bearer $KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"tenant_slug\":\"myorg\",\"ttl_seconds\":86400}' | jq -r .token)\n```\n\n```html\n\u003ciframe\n  src=\"http://localhost:8091?token=et_xxxx\"\n  width=\"100%\"\n  height=\"700\"\n  frameborder=\"0\"\n/\u003e\n```\n\nTheming (logo, accent colour, font) is configured in the admin portal under **Branding** and applied automatically.\n\n---\n\n## Git Push-to-Deploy\n\nConnect a snippet to a GitHub repo:\n\n```bash\ncurl -s -X POST http://localhost:8080/v1/snippets/$SNIPPET/git-integration \\\n  -H \"Authorization: Bearer $KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -d '{\"provider\":\"github\",\"repo_url\":\"https://github.com/you/repo\"}' | jq\n# returns { \"secret\": \"whsec_...\" } — add as a GitHub webhook secret\n```\n\nConfigure your GitHub webhook to point at `http://your-host:8080/v1/webhooks/git/$SNIPPET_ID`.\n\n| Push target | Deploys to |\n|-------------|-----------|\n| `main` / `master` | staging |\n| Any other branch | dev |\n| Tag `v*` | prod |\n\n---\n\n## API Reference\n\n### Authentication\n\n| Token type | Header | Used for |\n|-----------|--------|---------|\n| API key | `Authorization: Bearer vl_xxxx` | All management + invocation |\n| JWT access token | `Authorization: Bearer \u003cjwt\u003e` | Admin portal sessions |\n| Embed token | `Authorization: Bearer et_xxxx` | Embed endpoints only |\n\nTenant context is resolved server-side from your authenticated API key/session (and active org for session auth).\n\n### Endpoints\n\n```\n# Snippets\nPOST   /v1/snippets\nGET    /v1/snippets\nGET    /v1/snippets/{id}\nDELETE /v1/snippets/{id}\n\n# Versions\nPOST   /v1/snippets/{id}/versions\nGET    /v1/snippets/{id}/versions\nPOST   /v1/snippets/{id}/versions/{n}/publish   ?env=dev|staging|prod\n\n# Invocation\nPOST   /v1/invoke/{snippet}                      X-Invoke-Mode: sync|async|stream\nGET    /v1/invocations/{id}                      poll async result\nPOST   /v1/invocations/{id}/replay\n\n# Canary\nPOST   /v1/snippets/{id}/canary                  { version_id, percent }\nDELETE /v1/snippets/{id}/canary\n\n# Secrets\nPOST   /v1/secrets\nGET    /v1/secrets\nDELETE /v1/secrets/{id}\n\n# Integrations (800+ OAuth providers)\nGET    /v1/integrations                          provider catalog\nGET    /v1/integrations/configured               configured providers for this tenant\nPOST   /v1/integrations/configured               configure a provider (OAuth credentials)\nDELETE /v1/integrations/configured/{key}\nGET    /v1/integrations/{provider}/docs          endpoints + code example for a provider\nGET    /v1/connect/info                          OAuth redirect URL to register with providers\nGET    /v1/tenant/connections                    connected accounts\nPOST   /v1/tenant/connections/session            open OAuth Connect UI\nPOST   /v1/tenant/connections                    record a completed connection\nDELETE /v1/tenant/connections/{provider}\n\n# Observability\nGET    /v1/logs/snippets/{id}                    ?limit\u0026env\u0026status\nGET    /v1/metrics/snippets/{id}                 ?window=1h|24h|7d\n\n# Tenants\nPOST   /v1/tenants\nGET    /v1/tenant/egress\nPUT    /v1/tenant/egress\nGET    /v1/tenant/branding\nPUT    /v1/tenant/branding\nGET    /v1/tenant/members\nPOST   /v1/tenant/members/invite\nDELETE /v1/tenant/members/{userID}\nGET    /v1/tenant/usage                          ?window=24h|7d|30d\nGET    /v1/tenant/audit-log                      ?limit\u0026action\u0026before (admin scope)\nGET    /v1/tenant/api-keys\nPOST   /v1/tenant/api-keys\nDELETE /v1/tenant/api-keys/{id}\n\n# Embed\nPOST   /v1/embed/tokens\nGET    /v1/embed/bootstrap\nGET    /v1/embed/snippets\nGET    /v1/embed/snippets/{id}\nGET    /v1/embed/snippets/{id}/metrics\nGET    /v1/embed/snippets/{id}/logs\n\n# Auth\nPOST   /v1/admin/auth/register\nPOST   /v1/admin/auth/login\nPOST   /v1/admin/auth/logout\nPOST   /v1/admin/auth/refresh\nGET    /v1/admin/auth/me\nGET    /.well-known/jwks.json\n```\n\n---\n\n## Project Structure\n\n```\nvelane/\n├── services/\n│   ├── control-plane/          # Go API server (chi, pgx, zap)\n│   │   ├── cmd/server/         # main.go, bootstrap.go\n│   │   └── internal/\n│   │       ├── api/            # router, handlers, middleware\n│   │       ├── auth/           # JWT + password auth providers\n│   │       ├── audit/          # append-only audit logger\n│   │       ├── config/         # env-based config\n│   │       ├── executor/       # Executor interface + remote/firecracker impls\n│   │       ├── models/         # domain types\n│   │       ├── nango/          # Nango API client (OAuth proxy)\n│   │       ├── observability/  # post-invocation pipeline\n│   │       ├── scheduler/      # sync/async/stream invocation\n│   │       ├── store/\n│   │       │   ├── postgres/   # all DB queries + migrations\n│   │       │   └── redis/      # job queue + warm pool\n│   │       ├── tenantprovider/ # shared vs namespaced executor routing\n│   │       └── worker/         # async job processor + webhook delivery\n│   ├── executor-runtime/\n│   │   ├── bun/                # Bun HTTP server (runner.ts)\n│   │   └── python/             # Python FastAPI server (runner.py)\n│   ├── mcp-server/             # MCP protocol server (HTTP/SSE + stdio)\n│   └── cli/                    # velane CLI (cobra)\n├── apps/\n│   ├── admin/                  # Admin portal — snippet editor + management (Vite + React)\n│   └── embed-dashboard/        # Embeddable iframe viewer (Vite + React)\n├── platform-libraries/         # Built-in Bun + Python libraries (auto-loaded)\n└── scripts/\n    └── load-test.js            # k6 load test for the invoke API\n```\n\n---\n\n## Development\n\n### Running tests\n\n```bash\n# Control plane unit tests (no external services required)\ncd services/control-plane\ngo test ./...\n\n# With integration tests (requires Postgres + Redis)\nTEST_DATABASE_URL=postgres://velane:velane@localhost:5432/velane \\\nTEST_REDIS_URL=localhost:6379 \\\ngo test ./...\n\n# MCP server\ncd services/mcp-server \u0026\u0026 go test ./...\n```\n\n### Load testing\n\n```bash\n# Requires k6 (brew install k6)\nk6 run scripts/load-test.js\n\n# Higher load\nVUS=50 DURATION=60s k6 run scripts/load-test.js\n```\n\n### Running frontends locally\n\n```bash\n# Admin portal — http://localhost:5173\ncd apps/admin \u0026\u0026 npm install \u0026\u0026 npm run dev\n\n# Embed dashboard — http://localhost:5174\ncd apps/embed-dashboard \u0026\u0026 npm install \u0026\u0026 npm run dev\n```\n\nBoth proxy `/api/*` to `http://localhost:8080` automatically.\n\n### Useful make targets\n\n```bash\nmake up      # docker compose up --build -d\nmake down    # docker compose down -v\nmake logs    # tail control-plane logs\nmake build   # compile control-plane locally\nmake tidy    # go mod tidy\n```\n\n---\n\n## Configuration\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `DATABASE_URL` | `postgres://velane:velane@localhost:5432/velane` | Postgres DSN |\n| `REDIS_URL` | `localhost:6379` | Redis address |\n| `BUN_EXECUTOR_URL` | `http://localhost:8081` | Bun executor URL |\n| `PYTHON_EXECUTOR_URL` | `http://localhost:8082` | Python executor URL |\n| `PORT` | `8080` | API listen port |\n| `WORKER_COUNT` | `5` | Async worker concurrency |\n| `ENCRYPTION_KEY` | *(ephemeral)* | 64-char hex AES-256 key for secret encryption |\n| `JWT_PRIVATE_KEY` | *(ephemeral)* | RS256 private key PEM |\n| `EXECUTOR_TYPE` | `process` | `process` or `firecracker` |\n| `S3_ENDPOINT` | *(AWS)* | S3-compatible endpoint (e.g. `http://minio:9000`) |\n| `S3_BUCKET` | `velane-logs` | Bucket for invocation logs |\n| `CLICKHOUSE_ADDR` | — | ClickHouse native address |\n| `REPLAY_ENABLED` | `false` | Store input payloads for invocation replay |\n| `BOOTSTRAP_EMAIL` | — | First-boot admin email (remove after first start) |\n| `BOOTSTRAP_PASSWORD` | — | First-boot admin password (remove after first start) |\n| `BOOTSTRAP_TENANT` | `default` | First-boot tenant slug |\n| `NANGO_SECRET_KEY` | — | Nango API secret key for OAuth proxy |\n| `NANGO_WEBHOOK_SECRET` | — | Signing secret for Nango webhook verification |\n| `NANGO_CONNECT_URL` | `http://localhost:3009` | Browser-accessible Nango Connect UI URL |\n| `NANGO_API_URL` | `http://localhost:3003` | Browser-accessible Nango API URL |\n\n\u003e **Production:** Always set `ENCRYPTION_KEY` and `JWT_PRIVATE_KEY` to stable values. Ephemeral fallbacks mean secrets cannot be decrypted and all JWTs are invalidated on every restart.\n\n---\n\n## Firecracker (VM-boundary isolation)\n\nFor hardware-level isolation, Velane supports [AWS Firecracker](https://firecracker-microvm.github.io/) microVMs:\n\n```yaml\nEXECUTOR_TYPE: firecracker\nFIRECRACKER_BINARY: /usr/local/bin/firecracker\nFIRECRACKER_JAILER_BINARY: /usr/local/bin/jailer\nFIRECRACKER_BUN_ROOTFS: /images/bun-rootfs.ext4\nFIRECRACKER_PYTHON_ROOTFS: /images/python-rootfs.ext4\nFIRECRACKER_KERNEL_IMAGE: /images/vmlinux\n```\n\nRequires `/dev/kvm` — runs on bare metal servers, AWS metal instances (e.g. `c5.metal`), GCP bare metal, and Hetzner dedicated. Falls back gracefully with a clear error on non-KVM hosts.\n\n---\n\n## Roadmap\n\n- [ ] OIDC / OAuth2 social login (Google, GitHub)\n- [ ] SAML for enterprise SSO\n- [x] Multiple connections per provider per tenant (e.g. two Salesforce orgs)\n- [ ] Real ClickHouse metrics writes (currently Postgres-backed stubs)\n- [ ] Real S3/MinIO log writes (interfaces wired, writes stubbed)\n- [ ] Firecracker rootfs image builder\n- [ ] Kubernetes Helm chart\n- [ ] Terraform modules (AWS / GCP)\n- [ ] OpenAPI spec generation from snippet code\n\n---\n\n## Contributing\n\n1. Fork the repo\n2. Create a branch: `git checkout -b feat/my-feature`\n3. Run tests: `cd services/control-plane \u0026\u0026 go test ./...`\n4. Open a pull request\n\nAll Go changes must pass `go vet ./...` and `go test ./...`. Frontend changes should build without TypeScript errors (`tsc --noEmit`).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabskrj%2Fvelane","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabskrj%2Fvelane","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabskrj%2Fvelane/lists"}