Verify CE end to end
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.
R2 — Named feature guards and one edition map (PRD, verbatim). Every cloud-only capability … has a stable name, and ONE file maps each name to the editions that include it. Code guards a feature by its name, not by `edition.IS_CE`.
R3/R5/R6/R7 (PRD, verbatim headings): R3 — CE caps: 3 agents, 3 provider accounts. R5 — Runner doctrine lives in the product. R6 — Memory is paid: `memory-on.md` does not ship. R7 — Runner subagents ship with the product.
R4 — Secret scan (PRD, verbatim). gitleaks over the built tree is the scan of record; no second scanner.
Availability (PRD, verbatim). Every capability here is build-time; nothing is behind a flag. Oracle for "on in the real deployment": the hand-run `mirrors.yml` `jaah-ce` jobs green, and `ce-staging` publish + install from staging (README § Publishing) showing R1/R3/R5/R6/R7 behaviour. The cloud console (dev.jaah.ai) must be unchanged: open Settings → SSO and SCIM and Billing on dev, observe they still work (regression oracle for R2's guard rewrite).
## Scope and approach
Child C6 of Architecture §7. This is a verification coder; it ends `no_pr` if everything is green.
1. Probe your own node first: docker, gitleaks, forge. If it lacks Docker, ask (header `Access`) for an h2-class node.
2. Build and check the tree from develop with `build_tree.py $T` and `check_tree.py $T` (gitleaks 0 findings).
3. Hand-run `mirrors.yml` with `mirror: jaah-ce` (NO publish) via `jaah-forge`. Jobs `ce-tree` and `ce-images` must be green.
4. Do a local CE install from the built tree with compose `build:` blocks (D3: no GHCR, no staging publish).
- Add the Anthropic API key account, and connect GitHub with the pasted token.
- Create a scratch PRIVATE repo under the token's own account with no `.claude/`, and a project on it. Delete the repo at the end.
5. Observe on the install: AC1.4 (fresh install with 0 projects; then 1 project + 1 node), AC3.2, AC5.2, AC6.1, AC7.2.
6. Check the final AC2.3 state: assert that `PENDING_SWEEP` in `tools/tests/test_editions.py` is empty. Removing the then-empty section is your one code change: a PR via the merge lane, with Jaah Deploy watched. Otherwise you end no_pr.
7. After the Jaah Deploy watch, run the cloud regression on dev: open Settings → SSO, SCIM and Billing on dev.jaah.ai with `org/console/dev-login`. If dev is unreachable from your node, record it deferred.
For anything red, file a focused fix-up follow-up with itemized 1-2 sentence requirements (per project instructions) rather than building it here, unless the fix is trivial and fits in your one PR. Also file a task for any broken or inconvenient UI you notice while testing (project instruction).
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)
- `mirrors.yml` `jaah-ce` hand run, no publish (AC1.3) | `jaah-forge` (task-authenticated) on GitHub `jaah-ai/jaah` | verified (from h2: `api get repos/jaah-ai/jaah/actions/workflows/mirrors.yml` returned the active workflow, and `api get repos/jaah-ai/jaah` reports `permissions.push` and `admin` true — the identity may dispatch; the dispatch itself is C6's write)
- Jaah Deploy watch per child PR | `jaah-forge` read verbs (`pr checks`, `ci log`) | verified (same forge identity and read probe as above)
- Local CE install from the built tree (AC1.4, AC3.2, AC5.2, AC6.1, AC7.2) | Docker on the coder's node; no registry login (compose `build:` blocks, D3) | verified (`docker` present on h2; C6 re-probes its own node first and, lacking Docker, asks for an h2-class node)
- Running agents on the local install (AC3.2, AC5.2, AC7.2) | one AI provider account on the local CE install — `me/jaah/system/anthropic_api_key` (Anthropic API key) | verified (on roster, `credential_get` succeeded; value not recorded)
- Repo the local CE install's project clones (AC3.2, AC5.2, AC6.1, AC7.2 — a user repo with no `.claude/agents/`) | `me/users/roman@gmind.tech/github_admin` (GitHub token), pasted into the local CE console's GitHub connection (pasted-token fallback); the project is a scratch **private** repo C6 creates under the token's own account (no `.claude/`), deleted at the end of C6 | verified (on roster; `credential_get` succeeded; a GitHub API `GET /user` with it answered 200 from h2; value not recorded)
- Cloud regression on dev (Settings → SSO/SCIM/Billing) | `org/console/dev-login` (operator login), dev control plane | deferred — credential verified (`credential_get` succeeded) but dev does not answer from node h2 (curl timeout); per D3 the C6 runner checks it after the Jaah Deploy watch from a node with reach, else records it deferred
- ce-staging publish + install from GHCR | GitHub user token for GHCR read | deferred — operator chose local build (D3); the user token on the roster has expired
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.
Verification child: build nothing beyond the one `PENDING_SWEEP` cleanup PR and trivial fixes; everything else red becomes a follow-up task.
Done means:
- AC1.1 (final combined tree) → verify: `python3 tools/community_edition/build_tree.py $T && find $T -path '*org_sso*' -o -path '*scim*' -o -path '*sso_policy*' -o -path '*token_billing*'` prints nothing; and every path the feature map (R2) assigns to `sso`, `scim`, `jaah_ai_credit`, `multi_org_tenancy` is absent from `$T`.
- AC1.3 (product still works) → verify: `mirrors.yml` run by hand with `mirror: jaah-ce` (no publish): jobs `ce-tree` and `ce-images` green — tree api migrates plain `postgres:18`, `/api/health` 200, console builds, api image boots past first run.
- 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. (Install from the local build per D3; screenshots of each state go in the report.)
- 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. (Final: `PENDING_SWEEP` empty.)
- AC3.2 (enforced end-to-end) → verify on an installed CE: queue 4 tasks on one project; observe exactly 3 runner sessions live and the 4th task requeued (no attempt spent) until one ends; start a 4th console agent while 3 run → refused with "Jaah Community Edition runs 3 agents at once. For more, use Jaah Cloud." Add a 4th provider account → refused with the accounts message.
- AC4.1 → verify: `python3 tools/community_edition/check_tree.py $T` reports 0 findings including gitleaks, after all of R1-R6 land (baseline today: 0 findings, 2109 files).
- AC5.2 → verify: `Dockerfile.api` copies from the product home; CE api image dispatches a task whose system prompt contains the charter text (run a task on an installed CE, open its session transcript, observe the "Runner Charter" heading).
- AC6.1 → verify: built tree has no `memory-on.md`; a CE dispatch carries the memory-off section ("Working memory") and no "Project memory" section.
- AC7.2 → verify: on an installed CE, a runner on a user repo with no `.claude/agents/` can call `Agent(subagent_type: "recon-explore")` successfully (transcript shows the subagent ran).
- Availability:
- the hand-run `mirrors.yml` `jaah-ce` jobs are green;
- `ce-staging` publish + install from staging is deferred (the operator chose local build, D3, and the GHCR user token has expired);
- cloud regression: dev Settings → SSO, SCIM and Billing still work (deferred if dev is unreachable from this node).
Activity
- Draft
- Ready