Skip to content

epic: Phase 6 — reproducible instance: portable configs, environments, GitOps #19

Description

@2000game

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

  1. 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).
  2. No environments story (feat: environments — per-instance state + dev→prod promotion workflow #22) — no profile concept, no dev→prod promotion.
  3. No CI loop (feat: GitOps loop — plan on PR, gated apply, scheduled drift detection #24) — plan/apply/drift are manual.
  4. Permissions ergonomics debt (feat: permissions ergonomics — domainId by reference, grant adoption, catalog lifecycle #25) — numeric domainIds, hand-captured catalog with no staleness check.
  5. 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).
  6. 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).
  7. 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)

  1. bug(get): list commands return only ChurchTools first page; raw errors hide status/body #50 — pagination + error rendering (small; unblocks instance discovery)
  2. bug(permissions): ct adopt grants assumes every scoped dataId is a group #49 — grant scope-dimension fix (blocks plan-to-no-op)
  3. feat: environments — per-instance state + dev→prod promotion workflow #22 — environments: per-instance state + promotion
  4. 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)
  5. feat(adopt): bulk/filtered adoption + auto-capture dynamic rulesets + warn on unknown declaration fields #51 — bulk adopt + dynamic-ruleset capture + unknown-field warning
  6. 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)
  7. chore: bootstrap eqrm/ct-structure — adopt the real Equippers scaffold #23 — finish the ct-structure bootstrap to a clean no-op
  8. feat: GitOps loop — plan on PR, gated apply, scheduled drift detection #24 — GitOps loop: plan on PR, gated apply, drift detection
  9. 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)
  10. 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)
  11. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    epicTracking issue grouping multiple sub-issues

    Type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions