Strip Jaah AI credit and tenant mail

Task 10762 · 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) 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". ## Scope and approach Child C2b of Architecture §7 (Architecture §6). **Map rows**, each `editions = ["cloud"]`. Re-render after editing. - `jaah_ai_credit`: `token_billing/**`, `durable/token_billing_effect.py`, `jaah_routing/**`, `routes/jaah_ai.py`, and the platform-bedrock surfaces (`routes/platform_bedrock.py`, prefix `/api/platform-bedrock`, web `settings/bedrock/*Section.tsx`). C1 will already have placed the bedrock surfaces in some row; move them to this one if they belong to Jaah AI credit, and record the call. - `tenant_mail`: `tenant_gmail/**`, `org_email`, `agent_email`. **Guard the Jaah AI credit reaches:** - `routes/agent/task_secrets.py:43` (top-level metering import → lazy import inside the guard); - `budgets.py:38` (`money`); - the `jaah_routing/*` lazies; - `bedrock/revocation.py:64`; - `cron_system_activities.py:980,983`; - `org_create.py:99`; - `workflow_registry.py:230,513`, which registers `token_billing_effect` by name. Use the existing `workflow_registry.py:524,531` edition pattern, rewritten to `enabled("jaah_ai_credit")`; - the comment at `durable/runtime.py:73`. **Guard the tenant mail reaches:** - `routes/triggers.py:35,40` (top-level `tenant_gmail`); - `automation_email.py:95,123,201-230`; - `system_mail.py:177-178`. **`budgets.py`.** If `token_billing/money.py` is a pure stdlib leaf, move it to `app/money.py` (core) and update its importers. Otherwise, guard `budgets.py`'s use with `enabled("jaah_ai_credit")` and keep CE budgets in plain integers. Record which in the PR body. **CE behaviour when off:** - No Jaah AI routing or credit. The model-call report records usage without metering. - The DBOS workflow is simply not registered in CE. No CE install ever held it (D2), so the `application_version` pin is unaffected. - Email triggers and actions are unavailable. Hiding them in the console is C3d's job. **Also:** - The `models/notifications.py:214` FK to `tenant_mail_addresses` stays (D1). - Delete your `PENDING_SWEEP` entries (tagged C2b). **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)` / `isEnabled(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` (jaahd: `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`. - Web: `if (!isEnabled('<slug>')) return null` / `isEnabled('<slug>') && <Row/>`. **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 and the allowlist.** - Tests that today monkeypatch `IS_CE` alone switch to the `edition_fixture(edition)` helper. - As you rewrite a site, delete its `PENDING_SWEEP` entry in `tools/tests/test_editions.py`. - 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. `models/metering.py`, `models/tenant_email.py` and the squashed baseline migration stay. No edition-forked schema, no new migration. Done means: - AC1.1 → verify: `python3 tools/community_edition/build_tree.py $T && find $T -path '*token_billing*' -o -path '*tenant_gmail*'` prints nothing; and every path the feature map assigns to `jaah_ai_credit` and `tenant_mail` is absent from `$T`. - AC1.2 → verify: `python3 tools/community_edition/check_tree.py $T` exits 0 (import closure intact: no shipped module imports a removed one outside an edition/feature guard). - CE-mode api tests: - a model-call report from a runner is accepted and recorded without metering; - budgets compute; - the durable workflow registry boots without `token_billing_effect`; - creating an automation with an email trigger or action is refused with the NOT_IN_CE answer, not a 500. - Cloud-mode metering and tenant-mail tests pass unchanged. - 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 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. - The PR's Jaah Deploy on GitHub succeeds. If not, fix it and re-merge; leave a cancelled or superseded deploy alone.

Outcome

Stripped Jaah AI credit + tenant mail from the CE tree. All reaches are guarded, money.py moved to core, and the CE tests are added. check_tree: 0 findings. Quick gate and changed-area suites green; review lanes pass. PR #7175 queued in the merge lane. Memory: none applied.

Pull request

Artifacts

Activity

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