buildmymcpserver/CHOICES.md

80 lines
4.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CHOICES.md
Decisions made during the autonomous Sprints 13 build where the spec was ambiguous or
where production-quality required a concrete pick.
## Stream transport: WebSocket over SSE
Spec lists both in different sections. The user's goal explicitly says
"WebSocket-streamed build flow", so the dashboard subscribes to build events via
`/v1/builds/:id/stream` WebSocket on the control-plane API. Generator-worker publishes
events to Redis pub/sub; API fans out per-WebSocket subscriber.
## Local container deploy (no Coolify in dev)
Spec targets Coolify on Hetzner for production. In dev the generator spawns containers
directly via the local Docker daemon (Docker Engine API on `/var/run/docker.sock` or
`npipe:////./pipe/docker_engine` on Windows). Each generated server gets a host port from
the `RUNNER_PORT_RANGE_*` window and is exposed at `http://localhost:<port>`. The
`coolify` adapter is interface-compatible so swapping in for production is a single import.
## Local addressing: ports not wildcard subdomains
`*.mcp.buildmymcpserver.com` requires DNS + Traefik + wildcard SSL — pointless on
localhost. Dev uses `http://localhost:<port>` for each generated container. Production
Traefik routing is wired but unused by `pnpm dev`.
## OAuth 2.1 Authorization Server lives in the control plane
The runner-template is a Resource Server only. The control-plane API is the AS:
issues codes, exchanges tokens, signs RS256 JWTs, exposes JWKS. Each generated server
verifies tokens against `${CONTROL_PLANE_URL}/oauth/jwks`. This matches the spec's
"token exchange not pass-through" mandate.
## Better-Auth: email magic link via console transport in dev
We wire Better-Auth with the email/password + magic-link plugin. In dev, magic-link
emails are written to the API stdout (so the developer can click them); production
plugs in Resend. GitHub OAuth is configured but only used if env vars are populated.
## Generator: Claude API call gated by env, mock fallback for offline dev
If `ANTHROPIC_API_KEY` is set, the worker calls the real Claude API
(`claude-opus-4-7`). If not, a deterministic mock returns a small "echo" tool so the
end-to-end build flow stays demoable without burning credits. The choice is logged in
build logs so users always know which path ran.
## Static checks: tsc + targeted regex scan
- `tsc --noEmit` on the rendered server code in a tmp dir.
- Regex scan for banned tokens: `eval(`, `Function(`, `child_process`, `fs.unlink`,
prompt-injection markers (`ignore previous instructions`, `disregard the above`).
- esbuild bundle produced for the runner so the image is one file + deps.
## Sandboxing: dev relaxed, prod flags documented
Dev containers run without `--read-only` / `--cap-drop=ALL` because Windows Docker
Desktop refuses some combinations. The production launch flags are baked into
`apps/generator/src/lib/deploy.ts` constants but commented `// prod-only` for clarity.
## ChatGPT install snippet
ChatGPT supports MCP via "Custom GPTs → Actions → Add MCP server" or the
research "Custom Connectors" surface. We render a copy block with `URL`,
`Auth: OAuth 2.1`, and a link to the install-flow page on chat.openai.com. If the
official deep link path changes, only `apps/web/lib/install-snippets.ts` needs editing.
## Tailwind v4 + shadcn registry
Tailwind v4 uses CSS-first config. shadcn components are vendored into
`apps/web/components/ui/*` — only the primitives the spec lists. No drop-in defaults
left untouched: every component has been re-styled against the design tokens.
## Stripe / metering / quotas: scaffolded only in Sprint 13
The schema + types are complete. Wired Stripe checkout / webhooks are Sprint 4
per spec, so we leave a clean seam in `apps/api/src/routes/billing.ts` but do not
implement the flow yet. Quotas are read-only in the dashboard.
## Drizzle: `migrate` strategy
Schema lives in `packages/db/src/schema.ts`. `pnpm db:push` is dev-only and pushes
schema directly. Migrations are generated via `pnpm db:generate` and applied via
`pnpm db:migrate` on first API boot. Local Postgres comes from docker-compose.
## Node 20 LTS, ESM everywhere
All packages are `"type": "module"`. `tsx` runs ts directly in dev. esbuild bundles
for prod. No CJS.
## Conventional commits per task, single branch
Single `main` branch, conventional-commits messages. No PR flow because this is one
autonomous run.