refactor(open-core): skip private submodules in recursive init, public ENTERPRISE.md, edition in /api/version (#1443) - #1448
Conversation
…c ENTERPRISE.md, edition in /api/version (#1443) - .gitmodules: update = none on both private submodules (.claude, src/backend/enterprise) — a fresh OSS clone + `git submodule update --init --recursive` completes without credentials (verified end-to-end, incl. `git clone --recurse-submodules`) - deploy-dev.yml: persist the local update=checkout override before init and judge success by the populated marker file — a skipped submodule exits 0, so the old exit-code check would have silently degraded the dev deploy to OSS-only with a green log - docs/ENTERPRISE.md (new): generic open-core seam install/verify doc — config-first opt-in (a one-shot --init --checkout copies `none` into local config and later plain updates silently skip again), HTTPS-PAT URL override, rebuild, verification via boot line / feature-flags / edition; existing-clone migration note (enterprise clones carry no protective local update key — .claude clones do) - GET /api/version: edition "oss"|"enterprise" + enterprise_features, both from entitlement_service.list_entitled_features() (same source as feature-flags — surfaces cannot diverge); function-local import so _set_for_testing stubs aren't bypassed; builder stays stdlib-pure with the values threaded as params; runtimes list un-staled (+codex, #1187) - CLAUDE.md: rewritten .claude one-time setup (config-first, 3 commands) + external-contributor path via the public abilities dev-methodology plugin; README: pointer note (submodules optional, no credentials) - build-without-submodule.yml: assert /api/version edition=oss (only end-to-end check of the handler wiring) - tests: edition/enterprise_features passthrough, runtimes list, static guard for the function-local import; registry entry; requirements §35.2 + architecture.md updated; learnings entry on update=none semantics Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Resolve by running |
…d), stale-submodule drift warning, prod-overlay comments Adversarial /review findings on PR #1448: - F1 (high): ENTERPRISE.md step 3 was factually wrong — the backend Dockerfile COPY allowlist excludes enterprise/, so a rebuild never bakes the submodule in; enterprise reaches the container ONLY via bind-mount. Rewritten: dev stack = restart (src/backend is already mounted at /app); prod stack = add the docker-compose.prod.enterprise.yml overlay to every invocation. Following the old text on prod dead-ended at "submodule not present". - F2 (medium): deploy-dev.yml — a failed update on a previously-mounted VM leaves the OLD checkout, so the populated-marker check printed a green "initialized at <sha>" for a stale tree. Now compares the checked-out SHA against the recorded gitlink and emits a ::warning:: on drift. - F3 (medium): docker-compose.prod.enterprise.yml comments told operators to run submodule commands that now silently no-op under update=none (verified: --remote also skips). Comments now require the one-time local update=checkout override and point at docs/ENTERPRISE.md. - F4 (low): docs/learnings overstated the trap as specific to --init --checkout — ANY init path (plain --init, clone --recurse-submodules) copies update=none into local config; corrected in ENTERPRISE.md, CLAUDE.md, learnings.md. - F5 (low): passthrough test now includes a deliberately mismatched edition/features pair so a builder that re-derives edition fails. Cross-repo follow-up filed: trinity-enterprise#88 (ENTERPRISE_LOCAL_DEV.md documents the same now-skipping commands; lives in the private submodule). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
/review (adversarial, second pass) — 2 findings fixed in All git mechanics were re-verified empirically by an independent reviewer (10 throwaway-repo experiments — config-key syntax, init-copy semantics, pre-existing-clone asymmetry, Fixed on the branch:
Follow-ups filed: trinity-enterprise#88 (private ENTERPRISE_LOCAL_DEV.md documents the same now-skipping commands), #1450-class comment-disclosure issue (main.py seam comment; pre-existing, out of scope here), #1447 (pre-existing stale test, unrelated). |
Review — LGTM ✅ (minor nits, none blocking)Read the full diff + verified against the tree. Clean, well-tested, all 18 CI checks green (incl. Verified during review:
Nits (follow-up, not blocking):
Nice work on the docs — |
Summary
.claude,src/backend/enterprise) now carryupdate = nonein.gitmodules— a fresh public clone +git submodule update --init --recursive(andgit clone --recurse-submodules) completes without credentials; git skips them with exit 0. Verified end-to-end in clean-room clones.docs/ENTERPRISE.mddocuments the generic open-core mechanism only (mount, HTTPS-PAT override, rebuild, verify) — passes theenterprise-docs-guardgrep (run locally).GET /api/versionnow returnsedition: "oss" | "enterprise"plusenterprise_features, both derived fromentitlement_service.list_entitled_features()— the same source as feature-flags, so the two surfaces can't diverge. Reflects live registration state, not submodule-on-disk. Drive-by: the hardcodedruntimeslist was stale (missingcodex, Codex harness MVP — pluggable agentic execution engine alongside Claude Code #1187).update = nonea skipped submodule exits 0, sodeploy-dev.yml's old exit-code success check would have silently degraded the dev deploy to OSS-only with a green log. It now persists the durableupdate = checkoutlocal override before init and judges success by the populated marker file..claudesetup rewritten to the verified config-first flow (a one-shot--init --checkoutcopiesnoneinto local config, so later plain updates silently skip again — the config line must come first), plus an external-contributor path via the publicabilitiesdev-methodology plugin. README gains a one-line pointer.Existing clones have no protective local
updatekey for the enterprise submodule (unlike.claude, whoseupdate = checkoutwas copied at init). After this lands, plaingit submodule updatestarts skipping it — run once:(Documented in
docs/ENTERPRISE.md;trinity-ops-publicrunbooks should pick this up too.)Changes
.gitmodules,.github/workflows/deploy-dev.yml,.github/workflows/build-without-submodule.ymlsrc/backend/main.py(_build_version_payload+get_version— builder stays stdlib-pure for the exec-slice test harness; handler importsentitlement_servicefunction-locally so_set_for_testingstubs work)docs/ENTERPRISE.md(new),README.md,CLAUDE.mddocs/memory/requirements/infrastructure.md(§35.2),docs/memory/architecture.md,docs/memory/learnings.mdtests/unit/test_926_version_endpoint.py(+3 tests, call sites updated),tests/registry.jsonTest Plan
pytest tests/unit/test_926_version_endpoint.py— 8/8 pass (passthrough, runtimes, static function-local-import guard).gitmodules:--init --recursiveskips both submodules, exit 0, no credential prompt (GIT_TERMINAL_PROMPT=0, SSH BatchMode)git config submodule.src/backend/enterprise.update checkout, plain--initgenuinely attempts the clonedocs/+CLAUDE.md— cleanbuild-without-submodule.ymlnow also asserts/api/version→edition: "oss"(end-to-end handler wiring)test_847_entitlement_seam.py::test_submodule_registers_audit_not_ssofails locally on submodule-mounted clones — pre-existing staleness vs the SSO-OIDC merge (feat(sso): OSS gated surface for enterprise SSO (OIDC) (#32) #1303), skips in CI; filed test: test_submodule_registers_audit_not_sso is stale since SSO-OIDC landed (#1303) — fails locally whenever the enterprise submodule is mounted #1447.Fixes #1443
🤖 Generated with Claude Code