# DO NOT DO — roadmap anti-goals and guardrails

Use this file as a hard constraint when running `/pm-brainstorm` and `/pm`. If a proposed milestone/task conflicts with any item below, reject it.

## Anti-goals

- Do not propose roadmap work that is not clearly tied to bex's project goals/pillars (`docs/ADR008-vision.md`) or current platform roadmap intent.
- Do not create milestones that are vague, non-testable, or missing observable outcomes.
- Do not create milestones for sub-hour work; keep those as inbox notes (`wN/NNN.md`).
- Do not add "nice-to-have" work that has no clear sequence/dependency/risk rationale for why it must happen now.
- Do not duplicate existing milestones/tasks without a clear gap analysis and replacement intent.
- Do not propose work that conflicts with established architectural boundaries (bex product code vs platform GitOps responsibilities).
- Do not include tasks that cannot define concrete files/resources/systems they touch.
- Do not treat speculative ideas as committed roadmap items without explicit source context.
- **Do not OAuth2-ize the first-party dashboard.** The dashboard authenticates with its Kratos session (HttpOnly cookie, same-site) — never make it a Hydra OAuth2 client, and never store OAuth access/refresh tokens (or Kratos session tokens) in browser-readable storage. IETF `draft-ietf-oauth-browser-based-apps` ranks browser-held tokens last (BFF/cookie-session first); Ory's own guidance is "first-party apps use Kratos sessions; Hydra is for third-party/machine clients". Local-dev cross-origin is a dev-workflow problem — solve it with the Vite dev proxy (`dashboard/.env.example`, same-origin tunnel), not by changing the production auth architecture. (Learned from a reverted, never-committed dashboard-as-OAuth2-client attempt, 2026-07-07; the corrected **provider-side** work is `w4/m9`, which keeps the dashboard on sessions.)
- **Do not hand-build a Hydra login/consent provider.** Kratos's native `oauth2_provider.url` integration accepts Hydra login challenges itself (the login UI only passes `login_challenge` through); at most a headless consent acceptor is needed. A custom provider app (in bex-api or the dashboard) re-implements what Kratos ships. (Same lesson from the reverted 2026-07-07 attempt; `w4/m9` is the corrected design.)
- **Do not build a "Link database to service" picker in the dashboard** (an "Add from database" env-var flow that inserts a managed database's connection string into a service's environment). Render has no such dashboard feature — its env editor offers only **+ Add Environment Variable** and **Add from .env** (verified against render.com/docs/configure-environment-variables, 2026-07-08); the Render flow is copy the Internal Database URL from the database page, paste it into the service's env vars, and the m8 Databases page (connection-info reveal + copy buttons) plus the existing Environment tab already cover that. Render's only first-class DB→service linkage is the Blueprint `fromDatabase` field (IaC) — if bex ever mirrors that, it's `bex.yml`/backend spec work (w1), not a dashboard picker. (Withdrawn from `/pm-brainstorm for w5`, 2026-07-08.)
- **Do not build hosted agent sandboxes (E2B-compatible execution environments) for now — pillar 5 is off the roadmap.** User decision 2026-07-08 (follow-up to `/pm-brainstorm for w2`): the Render-alternative core — in-cluster builds (w1/m5), tenancy + enforced authz (w1/m9), elasticity (w1/m3), Render parity (w1/m13, w2/m4–m5) — is unfinished, and sandboxes are a second product surface competing for the same worker capacity; the mechanism is also single-host-only today (opensandbox Docker runtime `:8077`; the k8s snapshot path is blocked — docs/ADR014-sandboxes.md D5/D6). Do not propose sandbox milestones, tasks, or adjacent UX/pricing work (e.g. the GitHub-premium-request consumption model discussed 2026-07-08) unless the user explicitly re-opens pillar 5. `w2/m3` removed 2026-07-08; the design record stays in docs/ADR014-sandboxes.md (ADR, status: proposed) so a future re-open starts from the settled architecture, not from scratch.
- **Do not firewall `:22`/`:6443` with a static source-IP allowlist (the w1/m7 t001 `bex-app` firewall).** Removed 2026-07-09 (Terraform `hcloud_firewall.app` + `app_cluster_name` var deleted from `infra/terraform/`). A static `allowed_ssh_cidrs` fits neither the operator (dynamic residential IP — locks himself out on the next lease) nor CI (GitHub-hosted runners use large dynamic egress ranges — locks out `deploy.yml`/`app-cluster.yml`). So `:22`/`:6443` stay **authentication-only** (key-only SSH gated by the `bex` key + kube TLS/RBAC), an accepted single-layer baseline recorded in [docs/ADR019-infra-credentials.md](../docs/ADR019-infra-credentials.md) §Decisions. If a network second layer is ever wanted, the correct form is **Tailscale/WireGuard** (lock to a stable tailnet, with a tailnet-joined self-hosted CI runner) — _not_ a static CIDR. Do not re-propose the static-allowlist firewall. (User decision 2026-07-09, after the t005 LB outage post-mortem surfaced that none of t001 had ever applied to prod anyway.)
- **Do not build the Render capabilities the parity audit marked deliberate non-goals** (the `—` rows in [docs/ADR018-render-parity.md](../docs/ADR018-render-parity.md); recorded here 2026-07-09 so `/pm-brainstorm`/`/pm` reject them — the ledger rows stay as the evidence map):
  - **Persistent disks** (Render `/disks` + Disks tab) — bex is stateless-first (managed Postgres/Key Value hold state); disks disable multi-instance + zero-downtime deploys, which fights the dense bin-pack + free-tier-sleep economics.
  - **Shell/SSH into instances, one-off jobs (`/services/{id}/jobs`), and user SSH keys** — all one exec surface: hosted execution is pillar 5, off the roadmap (see the sandboxes entry above). Reopens only if the user reopens pillar 5.
  - **Static-site CDN cache purge** — Render's `POST …/cache/purge`. bex's static-server caches immutable per-revision objects (a deploy is a new revision ⇒ a new prefix, so there is nothing stale to purge), so an explicit purge API has no job to do — non-goal. (Header rules + redirects/rewrites were the other half of this row; they **shipped** in `w1/m21` once `w1/012` was promoted — see [render-parity.md](../docs/ADR018-render-parity.md) and [docs/ADR029-static-sites.md](../docs/ADR029-static-sites.md).)
  - **External log/metric drains** (Render `owner-log-stream`/`resource-log-streams`/`owner-metrics-stream`) — third-party observability-drain integrations, non-goal.
  - **Enterprise/managed-infra surfaces: SSO/SAML · SCIM, maintenance runs, dedicated outbound IPs** — non-goal for now (Ory can add SSO later if it ever matters).
  - **Workflows & tasks** (Render's `/workflows`/`/tasks`/`/task-runs` orchestration product) — an orchestration surface, not a hosting primitive; off-roadmap.
- **Do not build PR preview environments** (Render `POST …/previews` + Previews tab — spin up a temp App per pull request, tear down on close/merge). Proposed as `w2/m11` during `/pm-brainstorm more` 2026-07-12 (unblocked by w2/m8–m9's GitHub App integration) and rejected by user decision the same day. Do not re-propose unless the user explicitly re-opens it.
- **Do not use vcluster (or any per-tenant virtual control plane) as a tenant isolation tier.** It only isolates the control-plane/API axis — a surface bex's Render-style product never exposes to tenants (they never touch Kubernetes) — while workloads still share the host kernel and network, so NetworkPolicy + a sandboxed runtime are still required regardless. It is **not** a security boundary. Per-tenant control planes also multiply operational surface (upgrade/backup/monitor N apiservers) and carry always-on overhead that fights bex's dense bin-pack + free-tier-sleep economics. The isolation ladder is **namespace (default) → microVM (Kata/Firecracker/gVisor, hard)**; "tenant wants their own kubectl/CRDs" is a niche BYO-Kubernetes product feature, not an isolation strategy. (Rejected w1/m6, 2026-07-07.)

## Minimum bar for a meaningful milestone

Every proposed milestone must include:

- goal linkage (which project goal/pillar it advances),
- expected outcome (observable impact),
- why now (dependency/risk/sequence rationale),
- definition of done with testable end state.
