Edge Functions deploy
Mushi Mushi ships Supabase Edge Functions under packages/server/supabase/functions/ (run pnpm docs-stats for the live count). For a working self-host you only need the minimal ingest + classification set below; deploy every function directory except _shared (or mirror .github/workflows/deploy-edge-functions.yml) for a complete instance. Include healthz for unauthenticated monitoring probes. The repo root guide SELF_HOSTED.md remains the authoritative step-by-step.
Minimal required (ingest + classify)
cd packages/server
npx supabase functions deploy api --no-verify-jwt
npx supabase functions deploy fast-filter --no-verify-jwt
npx supabase functions deploy classify-report --no-verify-jwtAlso deploy mcp if you use the hosted MCP transport, and healthz for unauthenticated monitoring:
npx supabase functions deploy mcp --no-verify-jwt
npx supabase functions deploy healthz --no-verify-jwtRun every deploy command from packages/server/ — the Supabase CLI looks for supabase/functions/ relative to the current directory. Running from the repo root will fail with “entrypoint path does not exist”.
Checking what is deployed
api answers GET /health and GET /v1/health without a key, with the
commit it was built from:
curl -s "$SUPABASE_URL/functions/v1/api/v1/health"
# {"status":"ok","version":"<commit sha>","deployed_at":"...","region":"us","hosting_region":"ap-northeast-1"}version is the sha stamped at deploy time, so it answers “did my deploy
land?” without reading logs — compare it with git rev-parse HEAD.
hosting_region is where the function actually runs, which matters when the
database lives elsewhere. The standalone healthz function reports the same
sha for uptime monitors that should not depend on the API router.
Common optional functions
npx supabase functions deploy fix-worker --no-verify-jwt
npx supabase functions deploy judge-batch --no-verify-jwt
npx supabase functions deploy intelligence-report --no-verify-jwt
npx supabase functions deploy generate-synthetic --no-verify-jwt
npx supabase functions deploy qa-story-runner --no-verify-jwt
npx supabase functions deploy pdca-runner --no-verify-jwt
npx supabase functions deploy inventory-crawler --no-verify-jwt
npx supabase functions deploy inventory-propose --no-verify-jwt
npx supabase functions deploy inventory-gates --no-verify-jwt
npx supabase functions deploy drift-walker --no-verify-jwt
npx supabase functions deploy contract-graph-builder --no-verify-jwt
npx supabase functions deploy a2a-push-notify --no-verify-jwt
npx supabase functions deploy test-gen-from-report --no-verify-jwt
npx supabase functions deploy telegram-webhook --no-verify-jwt
npx supabase functions deploy cursor-webhook --no-verify-jwt
npx supabase functions deploy agent-status-poll --no-verify-jwt
npx supabase functions deploy agent-pr-review --no-verify-jwt
npx supabase functions deploy recipe-collector --no-verify-jwt
npx supabase functions deploy radar-scan --no-verify-jwt
npx supabase functions deploy operator-digest --no-verify-jwt
npx supabase functions deploy store-review-intake --no-verify-jwtFor closed-loop evolution workers (mistake-clusterer, mistake-summarizer, release-builder, experiment-analyzer, anomaly-detector, …) and cron setup, follow SELF_HOSTED.md.
Function inventory (core pipeline)
| Function | Trigger | What it does |
|---|---|---|
api | HTTP (Hono gateway) | All admin console + SDK API calls — routes under /v1/ |
fast-filter | Invoked by api | Stage-1 cheap triage before full classification |
classify-report | reports INSERT | LLM triage: severity, category, blast-radius |
mcp | HTTP | Hosted MCP transport for Cursor / Claude |
fix-worker | Fix dispatch (POST /v1/admin/fixes/dispatch, autofix) | Drafts a fix and opens a draft PR, or dispatches a Cursor / GitHub cloud agent |
judge-batch | cron (nightly) | Grades recent classifications; writes classification_evaluations and reports.judge_score |
intelligence-report | cron / manual | Weekly LLM narrative from KPI trends |
drift-walker | HTTP | Rebuilds the contract snapshot and compares it with the stored contract_snapshots baseline |
contract-graph-builder | HTTP | Builds a contract snapshot from the OpenAPI spec, inventory API dependencies and the latest Supabase schema snapshot |
pdca-runner | pdca_runs INSERT | Runs one PDCA iteration: fix → judge → promote cycle |
qa-story-runner | cron (every minute) | Runs QA Coverage stories on schedule via Firecrawl / Browserbase |
generate-synthetic | cron | Playwright-based synthetic smoke tests |
inventory-crawler | cron / manual | Crawls app routes to populate inventory_nodes |
inventory-propose | manual | Proposes user-story inventory from crawl data |
inventory-gates | manual | Runs gate checks (dead handlers, mock leaks) |
a2a-push-notify | manual / agents | Sends A2A protocol notifications to connected agents |
test-gen-from-report | manual | Generates a Playwright test from a report, opens draft PR |
telegram-webhook | Telegram Bot API | Voice-note inbox: secret-token auth, /start <code> project binding, transcript + inline-keyboard confirmation |
cursor-webhook | Cursor Cloud Agent (v0 callback) | Receives statusChange callbacks, writes fix_attempts.pr_url, notifies |
agent-status-poll | cron (5-55/5) | Polls open Cursor / GitHub cloud-agent runs and closes them (PR URL, failure) |
agent-pr-review | cron (3-53/10) + re-run route | Reviews each fix PR with Claude Opus 5.5 on the project’s Anthropic key; a merge verdict readies the draft (with no review possible, a fix-worker draft falls back to its own self-check), and a “hold” blocks merging from Mushi Mushi without an override |
review-followup | cron (6-56/10) | Sends “fix first” findings back to a cloud agent on the same PR (off by default) |
fix-verifier | cron (4-54/10) + verify route | Checks the merge gates for a PR’s head; merges only when verified auto-merge is on |
merge-queue | cron (1-56/5) + queue route | ”Merge when ready” and release trains |
The remaining workers (billing, retention, SDK upgrade, skill-sync, rewards payout, …) live alongside these. Full list: ls packages/server/supabase/functions/ or pnpm docs-stats.
Required secrets
Set secrets before deploying — functions read them at cold-start:
cd packages/server
npx supabase secrets set ANTHROPIC_API_KEY=sk-ant-…
npx supabase secrets set OPENAI_API_KEY=sk-…
npx supabase secrets set LANGFUSE_PUBLIC_KEY=pk-lf-…
npx supabase secrets set LANGFUSE_SECRET_KEY=sk-lf-…
npx supabase secrets set LANGFUSE_BASE_URL=https://cloud.langfuse.com
npx supabase secrets set SENTRY_DSN_SERVER=https://…@sentry.io/…
npx supabase secrets set GITHUB_APP_ID=…
npx supabase secrets set GITHUB_APP_PRIVATE_KEY="$(cat path/to/key.pem)"
npx supabase secrets set FIRECRAWL_API_KEY=…
npx supabase secrets set ADMIN_BASE_URL=https://your-domain.example.com/adminTenants can override ANTHROPIC_API_KEY and OPENAI_API_KEY per project via BYOK.
The server-wide GITHUB_TOKEN, SLACK_BOT_TOKEN and LANGFUSE_* keys belong to the operator’s own accounts, so they count as an app’s own GitHub, Slack or Langfuse connection only for apps owned by a user listed in MUSHI_OPERATOR_USER_IDS (comma-separated user ids). The pipeline’s own Langfuse tracing still uses the keys for every app. Every other app connects its own GitHub (the GitHub App, or a token on its Integrations page) and its own Slack. On a single-team self-host, put your own user id there, or the server-wide token serves no app. E2B_API_KEY is read by the Node fix orchestrator in @mushi-mushi/agents, not by the edge functions; set it where that runs if you use the E2B sandbox.
JWT verification
Functions set verify_jwt = false in packages/server/supabase/config.toml. Auth is enforced inside each handler via one of two patterns:
- Service-role guard (
requireServiceRoleAuth) — cron-triggered functions (intelligence-report,pdca-runner,judge-batch, etc.) verifyMUSHI_INTERNAL_CALLER_SECRETor the Supabase service-role key in theAuthorizationheader, so only the scheduler and other server functions can call them. - User / API-key guard — user-facing functions (
api,mcp,classify-report, etc.) authenticate via API key or JWT inside the handler.
This two-layer approach lets functions be deployed with --no-verify-jwt while keeping security equivalent to the platform default. See packages/server/supabase/config.toml for the per-function settings.