Skip to content

feat: portable configs — logical references instead of numeric CT ids (shared resolver) #20

Description

@2000game

Make configs portable across ChurchTools instances by replacing hardcoded numeric CT ids with logical references, resolved per host at plan time. Part of the Phase 6 epic; the keystone for dev→prod reproducibility (ids differ per instance, so any config carrying raw ids can only ever target one instance).

The Phase 5 design spec already proposed this (§ Shared resolver) but it was not built — resolution today is manual everywhere.

Current id-hardcoding surface

  • ct.group({ groupTypeId: 1, groupStatusId: 2 }) — raw ids in the DSL (src/config/context.ts)
  • Permission domainId supplied manually (docs/permissions.md; src/permissions/types.ts)
  • Dynamic-group ruleset var values: q.eq("ctgroup.campusId", 4) — raw ids in JSONLogic (src/config/query.ts)
  • Permission scope keys already resolve, but only against tool-managed groups (src/permissions/scope.ts, "MVP" comment)

Scope

  • Central resolver: logical key/name → CT id, sourced from (a) the state file for managed resources, (b) live catalogs for referenceable master data (group types, group statuses via read-only /group/memberstatus, campuses, roles via /group/roles). One implementation, used by all four surfaces above.
  • DSL accepts logical references with the numeric escape hatch retained:
    ct.group({ key: "mainz_kids", groupType: "ministry_team", status: "active", campus: "mainz" })
  • Typed-query helpers resolve names: q.eq("ctgroup.campusId", ref.campus("mainz")).
  • Permission domain objects declared by keys, e.g. ct.groupRole({ group: "mainz_kids_lead", role: "Leiter", ... }) — requires freezing the group_role domainId semantics (open item 2 in the Phase 5 spec: role-def id vs per-(group,role) id; confirm live on eqrm-dev).
  • Resolution happens in buildPlan (per-host); unresolvable keys fail the plan with a clear error naming the key and where it was referenced.
  • Resolver results are not persisted in config — only state carries ids.

Acceptance criteria

  • An example config containing zero numeric CT ids plans and applies correctly against eqrm-dev.
  • The identical config file produces a valid plan against a second host without edits (ids resolved per instance).
  • Unresolvable reference → plan-time error with key + reference site; no partial apply.
  • Unit tests for each resolution source; round-trip integration test env-gated on eqrm-dev.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions