Goal: close the gap between "a working plan/apply CLI" (Phases 0–5) and the north star from the design doc : the overarching structure of our ChurchTools instance described as reproducible, versionable desired-state code — rehearsable on dev, promotable to prod, continuously reconciled. Part of #1 .
Where we stand (2026-07-09)
Phases 0–5 are merged. Done since this epic opened: portable configs / logical references (#20 ), group↔campus + field coverage (#21 ), Phase-4 robustness (#17 ), manual-surface runbook (#26 ), and the review-wave bug fixes #27 –#35 . Bootstrapping the real eqrm/ct-structure repo has begun — ~48 resources adopted — and surfaced the current sub-issue wave (#47 –#52 ; bugs #36 , #49 , #50 ).
Remaining gap
Bootstrap is not at plan-to-no-op (chore: bootstrap eqrm/ct-structure — adopt the real Equippers scaffold #23 ) — blocked by the grant scope-dimension bug (bug(permissions): ct adopt grants assumes every scoped dataId is a group #49 ), first-page-only pagination (bug(get): list commands return only ChurchTools first page; raw errors hide status/body #50 ), and environments (feat: environments — per-instance state + dev→prod promotion workflow #22 ).
No environments story (feat: environments — per-instance state + dev→prod promotion workflow #22 ) — no profile concept, no dev→prod promotion.
No CI loop (feat: GitOps loop — plan on PR, gated apply, scheduled drift detection #24 ) — plan/apply/drift are manual.
Permissions ergonomics debt (feat: permissions ergonomics — domainId by reference, grant adoption, catalog lifecycle #25 ) — numeric domainIds, hand-captured catalog with no staleness check.
Adoption is one-resource-at-a-time (feat(adopt): bulk/filtered adoption + auto-capture dynamic rulesets + warn on unknown declaration fields #51 ) and configs aren't human-friendly to author (feat(dx): human-authorable configs — idiomatic adopt output, dynamic sugar, located errors, machine-only state, blueprints by default #52 ).
Structural schema gaps — person master-data field definitions + security levels (feat: manage person master-data field definitions + expose security levels (schema, not people) #47 ), custom field definitions (feat: support custom field definitions (group custom fields; person custom fields) #48 ).
Unverified convergence assumption — dynamic ruleset round-trip (bug: dynamic ruleset round-trip assumption unverified — CT-recomputed fields would cause perpetual diffs #36 ).
Accepted ChurchTools API limits (we work around, not against)
Limit
Consequence
group_status has no write endpoint (GET /group/memberstatus only)
statuses stay manual; resolve by name read-only
Meeting points have no endpoint at all
fully manual, runbook item
name↔authId bridge absent from REST (legacy churchauth getMasterData only)
static catalog + regeneration script per CT release
Dynamic groups have no create/delete entity endpoint
shell group + ruleset (already modeled)
Permissions & dynamic-group APIs flagged "preliminary"
pinned by env-gated round-trip tests
People/memberships
out of scope by design, hard-guarded
Plan (ordered)
bug(get): list commands return only ChurchTools first page; raw errors hide status/body #50 — pagination + error rendering (small; unblocks instance discovery)
bug(permissions): ct adopt grants assumes every scoped dataId is a group #49 — grant scope-dimension fix (blocks plan-to-no-op)
feat: environments — per-instance state + dev→prod promotion workflow #22 — environments: per-instance state + promotion
feat: permissions ergonomics — domainId by reference, grant adoption, catalog lifecycle #25 — permissions ergonomics (needs the resolver, which exists since feat: portable configs — logical references instead of numeric CT ids (shared resolver) #20 )
feat(adopt): bulk/filtered adoption + auto-capture dynamic rulesets + warn on unknown declaration fields #51 — bulk adopt + dynamic-ruleset capture + unknown-field warning
feat(dx): human-authorable configs — idiomatic adopt output, dynamic sugar, located errors, machine-only state, blueprints by default #52 — human-authorable configs (tool-side items; blueprint rewrite lands with chore: bootstrap eqrm/ct-structure — adopt the real Equippers scaffold #23 )
chore: bootstrap eqrm/ct-structure — adopt the real Equippers scaffold #23 — finish the ct-structure bootstrap to a clean no-op
feat: GitOps loop — plan on PR, gated apply, scheduled drift detection #24 — GitOps loop: plan on PR, gated apply, drift detection
bug: dynamic ruleset round-trip assumption unverified — CT-recomputed fields would cause perpetual diffs #36 — pin the dynamic-ruleset round-trip on eqrm-dev (anytime; independent)
feat: manage person master-data field definitions + expose security levels (schema, not people) #47 / feat: support custom field definitions (group custom fields; person custom fields) #48 — schema surface (independent; feat: manage person master-data field definitions + expose security levels (schema, not people) #47 also feeds bug(permissions): ct adopt grants assumes every scoped dataId is a group #49 's scope dimensions)
feat: automated releases — install ct from the GitHub Releases page #9 — automated releases (independent; feat: GitOps loop — plan on PR, gated apply, scheduled drift detection #24 's CI wants installable binaries)
Definition of done for the epic: a new campus's full scaffold (groups, hierarchy, grants, auto-groups) is created on prod by merging a PR in ct-structure that was first rehearsed against eqrm-dev — with zero numeric ids in the config and zero manual CT clicks beyond the documented runbook items.
Goal: close the gap between "a working plan/apply CLI" (Phases 0–5) and the north star from the design doc: the overarching structure of our ChurchTools instance described as reproducible, versionable desired-state code — rehearsable on dev, promotable to prod, continuously reconciled. Part of #1.
Where we stand (2026-07-09)
Phases 0–5 are merged. Done since this epic opened: portable configs / logical references (#20), group↔campus + field coverage (#21), Phase-4 robustness (#17), manual-surface runbook (#26), and the review-wave bug fixes #27–#35. Bootstrapping the real
eqrm/ct-structurerepo has begun — ~48 resources adopted — and surfaced the current sub-issue wave (#47–#52; bugs #36, #49, #50).Remaining gap
Accepted ChurchTools API limits (we work around, not against)
group_statushas no write endpoint (GET /group/memberstatusonly)churchauth getMasterDataonly)Plan (ordered)
Definition of done for the epic: a new campus's full scaffold (groups, hierarchy, grants, auto-groups) is created on prod by merging a PR in ct-structure that was first rehearsed against eqrm-dev — with zero numeric ids in the config and zero manual CT clicks beyond the documented runbook items.