Console feature guards and upsell page

Task 10766 · Running · Coder · created · updated

Epic 10745 "Close the identified gaps in Jaah CE". Original request (verbatim): "Close the identified gaps in Jaah CE". Settled inputs: PRD (Task 10746) and Architecture (Task 10747). Requirement and AC ids below are the PRD's; section refs (§) are the Architecture's. Read them with task_read on 10746/10747 if you need more than is quoted here. ## Requirement (verbatim) R1 — Enterprise code does not ship in the CE tree (PRD, verbatim). The SSO, SCIM, token-billing and multi-org tenancy feature modules are absent from the built public tree, not just their routes. Today `apps/api/app/org_sso.py`, `sso_policy.py`, `scim.py`, `token_billing/`, `tenancy/` and `tenant_gmail/` all ship inert. Operator's words: "Decide whether enterprise code ships in the mirror." → "Strip enterprise code" / "Exclude from tree". R2 — Named feature guards and one edition map (PRD, verbatim). Every cloud-only capability (everything CE leaves out today — billing, cloud node launch, node groups, Multi-Node Hosts, NodeLink, MicroVM, GHA runners, knowledge base, project memory, SSO, SCIM, SIEM export, tenant mail, data residency, org transfer, sign-up/users, … — plus R1's enterprise features) has a stable name, and ONE file maps each name to the editions that include it. Editions in the map today: `cloud` and `ce`; the map must accept a further edition (e.g. `onprem`, `enterprise`) by adding a column/entry only. Code guards a feature by its name, not by `edition.IS_CE`. ## Scope and approach Child C3d of Architecture §7 (Architecture §6 "Console"). **Sweep.** Rewrite every per-feature `IS_CE` in `apps/web/src` to `isEnabled('<slug>')`. - C2a owns the SSO/SCIM web files. - `cloudSurfaces.ts` and `settingsCloud.tsx` stay as the lazy-glob file seam. An all-cloud bundle may keep `IS_CE` as an edition-wide file seam. - The authoritative site list is the `PENDING_SWEEP` entries C1 tagged C3d. Delete each as you rewrite it. **Map.** Fill the map's `console_routes` for each removed console surface (billing, SSO, SCIM, org switch/tenant, node groups, NodeLink, …). Re-render so `REMOVED_CONSOLE_ROUTES` lists them. **`NotInEdition` page.** - For each `REMOVED_CONSOLE_ROUTES` entry, the router mounts `<NotInEdition feature=…>`. - It reuses `components/CloudUpsell.tsx`. The heading is the feature's `LABELS` value. The body is the existing sentence "Not in Jaah Community Edition. Available on Jaah Cloud." plus the upgrade link (`CLOUD_SIGNUP_URL`). - It is a real page, not a redirect. - Hide in-app links to those routes with `isEnabled` guards (Settings, left rail, org switcher). **Standards.** Follow `docs/standards/ui-style-guide.md` and `docs/standards/ui-copy-standards.md`. **Seam** (Architecture §2, pinned by C1; build against it). - The map is `packages/editions/features.toml`, rendered to `apps/web/src/lib/editionFeatures.ts`: `FeatureName`, `ENABLED`, `isEnabled`, `LABELS`, `REMOVED_CONSOLE_ROUTES`. - After any map edit, regenerate with `python3 tools/editions/render.py --edition cloud --out .`; a freshness test diffs it. - Web idioms: `if (!isEnabled('<slug>')) return null` / `isEnabled('<slug>') && <Row/>`. - CE-mode web tests use the `test/edition.ts` `edition_fixture` helper, not a bare `IS_CE` mock. - If a site you own is really edition-wide, move it to `EDITION_WIDE` with a one-line reason. Credentials & reach: (Architecture §10 rows, verbatim) - Build, check (incl. gitleaks), tooling + app test suites | worktree only; gitleaks at `~/.local/bin/gitleaks` on node h2 | verified (binary present on h2) - Jaah Deploy watch per child PR | `jaah-forge` read verbs (`pr checks`, `ci log`) | verified (same forge identity and read probe as above) Out of scope: (PRD §3, verbatim — do NOT touch) - MUST NOT make `jaah-ai/jaah-ce` public, change repo visibility, or run a `ce-mirror` publish. - MUST NOT edit LICENSE text or any legal page (legal review is a human item). - MUST NOT edit `docs/pricing.md` or the marketing site (deferred to the flip; not in this repo). - MUST NOT add a second secret scanner (trufflehog etc.). - MUST NOT add an env var, setting, build arg or runtime flag that selects an edition, enables a feature or moves a cap. - MUST NOT change cloud behaviour or cloud plan entitlements/pricing; the R2 guard rewrite is behaviour-preserving for `cloud`. - MUST NOT ship `.claude/skills/` (translate, marketing-copy) — named a deferred follow-up below. - MUST NOT build an on-prem or enterprise edition — only make the map able to describe one. Architecture boundaries: - D4/D5: no monorepo file moves. - D1: keep schema, strip logic, no new migration. - The SSO/SCIM web files are C2a's. Done means: - AC1.4 (UI) → verify: install the built CE (README quick start), sign in, open Settings and the left rail: no SSO, SCIM, billing or org-switch/tenant surface is visible; any link to such a surface shows the CE upgrade message (`Not in Jaah Community Edition. Available on Jaah Cloud.` + upgrade link), never a blank page, 500 or raw error. States: fresh install with 0 projects; install with 1 project and 1 node. - Here: CE-mode web unit/e2e tests cover each `REMOVED_CONSOLE_ROUTES` path. Each renders the page with the label heading, the sentence and a working upgrade link. - Settings and the left rail render no removed entry. - The installed-CE walk-through is C6's. - Tightened: the page is legible and laid out like the rest of the console at desktop and phone width (no horizontal scroll, readable heading, the link a visible button or link). Put screenshots of both widths in the PR. - AC2.3 → verify: `grep -rn "edition.IS_CE" apps/api/app apps/jaahd apps/web/src` shows only the guard mechanism itself and edition-wide behaviour (caps, loopback, bootstrap), no per-feature check; each per-feature check names a feature from the map. (Here, for `apps/web/src`: no C3d-tagged entry remains in `PENDING_SWEEP`.) - AC2.6 (copy) → every feature name a person sees (upgrade message, docs) is a human label, never the slug. - Every entry added to `EDITION_WIDE` falls in a §2.3 category and is listed with its reason in the PR body. Moving a per-feature site there to dodge the rewrite fails review. - Cloud console unchanged: - web tests in cloud mode pass unchanged; - in cloud mode, the Settings → SSO, SCIM and Billing routes render their real pages. - Quick gate `./dc check quick` green, including `tsc -b`/`vite build`. - `build_tree.py $T && check_tree.py $T` exits 0. - The PR's Jaah Deploy on GitHub succeeds. If not, fix it and re-merge; leave a cancelled or superseded deploy alone.

Activity

  • Draft
  • Ready
  • Runner started