Sweep API org, billing, identity guards
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)
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`.
Operator's words (Q2): "Let's guard each feature with its name and maintain a map of what is included in CE. that will give us a way to create other types of distribution, e.g. for on-premises usage or enterprise, etc. Do a deep research for the best practice" → map scope: "Every cloud-only feature".
R6 (PRD, verbatim): Memory is paid: `memory-on.md` does not ship. Project memory is a cloud feature in the R2 map; its doctrine file is excluded with it.
## Scope and approach
Child C3b of Architecture §7.
Rewrite the remaining per-feature `edition.IS_CE` checks in `apps/api/app` to `edition_features.enabled("<slug>")`. The areas:
- billing, plans and budgets;
- orgs;
- credentials, account sharing and api keys;
- signup and users;
- support and site chat;
- data residency, SIEM and tenant notifications;
- automations and triggers;
- tasks/stream and live cast;
- the project-memory skip in `dispatch_compose/system_prompt.py` `build_system_prompt` → `enabled("project_memory")`. It is a feature check, NOT edition copy.
The authoritative site list is the `PENDING_SWEEP` entries C1 tagged C3b; delete each as you rewrite it. Sites that are edition-wide per §2.3 (e.g. prompt-composition edition copy) move to `EDITION_WIDE` with a reason.
C2a and C2b own some of the enterprise reaches in your files: `auth.py` SSO, `routes/orgs.py` sso_policy, triggers/tenant mail and budgets money. Leave those lines to them. File overlap is fine; rebase at merge.
**Seam** (Architecture §2, pinned by C1; build against it).
- The edition map is `packages/editions/features.toml`. A row has a slug, `label`, `editions`, and optional `paths`, `route_prefixes` and `console_routes`.
- The rendered modules expose `enabled(name)`.
- After any map edit, regenerate with `python3 tools/editions/render.py --edition cloud --out .`; a freshness test diffs them.
**Guard idioms** (§2.3, the ONLY forms check_tree honours).
- Python: `from app import edition_features`, then either `if edition_features.enabled("<slug>"):` with the feature module imported lazily inside, or the early exit `if not edition_features.enabled("<slug>"): return …` before the import.
- Never `from app.edition_features import enabled`.
**Where `edition.IS_CE` stays.** Only for the edition-wide traits listed in §2.3. For a site in doubt: if a future edition could plausibly include the behaviour without the rest of the single-user package, it is a feature.
**Tests.** Tests that today monkeypatch `IS_CE` alone switch to the `edition_fixture(edition)` helper, which sets `EDITION`, `IS_CE` and `ENABLED` together.
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.
- Cloud plan entitlements stay in `org_plans`/`plan_terms`, not the map.
Done means:
- 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 the C3b-tagged sites: none remain in `PENDING_SWEEP`, and each now names a map feature.)
- AC6.1 (dispatch side, unit level):
- a CE-mode `build_system_prompt` (`edition_fixture("ce")`) carries the memory-off section ("Working memory") and no "Project memory" section;
- a cloud-mode one with memory on carries "Project memory";
- the installed-CE observation is C6's.
- 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 behaviour preserved (PRD §3):
- the changed-area api test suites pass in cloud mode with their assertions unchanged;
- the CE-mode tests for each rewritten site run under `edition_fixture("ce")` and assert the off behaviour;
- a guard with the wrong slug or polarity fails at least one test.
- Quick gate `./dc check quick` green.
- `python3 tools/community_edition/build_tree.py $T && python3 tools/community_edition/check_tree.py $T` exits 0 (AC1.2).
- The PR's Jaah Deploy on GitHub succeeds. If not, fix it and re-merge; leave a cancelled or superseded deploy alone.
Outcome
C3b sweep: all 56 C3b IS_CE sites in apps/api/app now use edition_features.enabled(slug); create_account cap→EDITION_WIDE; table-driven slug/polarity tests + AC6.1. Quick gate, full API suite (27777 passed), CE tree check green; reviews pass. PR #7173 queued in merge lane; Jaah Deploy runs after the lane merges. Memory: none applied.
Artifacts
Activity
- Draft
- Ready
- Runner started
- Runner ended (done)