Sweep jaahd per-feature edition checks

Task 10765 · Done · 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) 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". ## Scope and approach Child C3c of Architecture §7. Rewrite every per-feature `edition.IS_CE` check in `apps/jaahd` to `edition_features.enabled("<slug>")`. - Known sites: `main.py:1663,1734-1745`, `fleet_launch.py:607`, `vnode_converge.py`, `microvm_mark.py`, `git_env.py:67`, …. - jaahd idiom: `import edition_features`. Keep `cloud_modules.load(name)` for by-name optional loads. - These stay `IS_CE`: the host-layout sites listed edition-wide in §2.3 (`host_platform/linux.py`, `environment.py`, `secret_modes.py`, `env_helpers.py`, `console_direct.py`, `agents/base.py`) and the CE subagent placement in `agents/agent_layer.py`. - The authoritative site list is the `PENDING_SWEEP` entries C1 tagged C3c. Delete each as you rewrite it. **Seam** (Architecture §2, pinned by C1; build against it). - The edition map is `packages/editions/features.toml`. The rendered module `apps/jaahd/edition_features.py` exposes `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). - 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 edition_features import enabled`. **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 and the allowlist.** - Tests that today monkeypatch `IS_CE` alone switch to the `edition_fixture(edition)` helper. - 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 CE subagent placement in `agents/agent_layer.py` is C5's. 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 `apps/jaahd`: no C3c-tagged entry remains in `PENDING_SWEEP`.) - 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 jaahd 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. - The CE node bundle still stages and its jaahd starts: the community-edition node tests (`tools/tests/test_community_edition.py` and the jaahd CE tests) pass under `python3 -m pytest`. - 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

jaahd per-feature IS_CE sites now use edition_features.enabled (microvm, multi_node_hosts, project_memory, tailnet, new node_log_archive). 5 host-layout sites moved to EDITION_WIDE. C3c is cleared from PENDING_SWEEP. Quick gate, CE suite and tree check green. PR #7174 queued. Memory: none applied.

Pull request

Artifacts

Activity

  • Draft
  • Ready
  • Runner started
  • Runner ended (done)