Skip to content

design: define aggregate adoption boundaries for composite resources #141

Description

@bwl21

Context

ct adopt currently follows technical API boundaries that are not necessarily visible to users. In the ChurchTools UI, users edit several related records as one domain object even when ChurchTools exposes them through separate endpoints.

Issue #135 is the first concrete example: group member-field definitions appear to belong to a group in the UI, but ct adopt group currently captures them only with --with-member-fields. Dynamic rules and hierarchy relationships have similar questions.

The same decision will recur for other resource types. For example, adopting an event may eventually involve registration-group definitions and resource bookings, while referenced shared resources have different ownership implications.

This should be decided once as a project-wide adoption contract rather than independently for every new resource.

Non-negotiable boundary

People are permanently out of scope, as defined by CONTRIBUTING.md. Adoption must never manage memberships, participants, registrations, attendance, or other person-related records. This issue only decides how non-person structural resources and relationships are grouped for adoption.

Decision to make

Define what it means for ct adopt <type> to adopt a composite domain object.

At minimum, distinguish:

  1. Root resource — the object explicitly selected by the user.
  2. Owned structural child resources — non-person records whose lifecycle belongs to the root, such as group member-field definitions or event registration-group definitions.
  3. Relationships — hierarchy edges or resource bookings that connect managed structural objects.
  4. Shared referenced resources — resources, calendars, groups, or other objects that may be reused elsewhere and should not silently become managed merely because they are referenced.
  5. Person-related data — permanently excluded, not a configurable adoption category.

Questions

  • Should owned structural child resources be adopted by default?
  • Should structural relationships be adopted by default, or only preserved as references?
  • Should shared referenced objects ever be adopted transitively?
  • Should the CLI provide individual --no-* switches, a --minimal mode, or explicit --with-* switches?
  • How deep may recursive structural adoption go, and how are cycles handled?
  • What happens when a child endpoint is unsupported or the user lacks permission: fail, warn, or continue only after explicit opt-out?
  • How should dry-run and normal output summarize what was adopted, referenced, skipped, excluded, or left unmanaged?
  • What backwards-compatibility policy applies when an existing opt-in becomes a default?

Examples to cover

Group

Event (future resource support)

  • core event properties
  • registration-group definitions owned by the event
  • resource bookings associated with the event
  • referenced shared resources and calendars
  • participants, registrations, and attendance: excluded

For example, adopting a resource booking must not automatically imply adopting the shared resource itself unless the project explicitly chooses that behavior.

Acceptance criteria

  • A documented, resource-independent adoption contract exists.
  • Default inclusion, reference-only, opt-in/opt-out, and excluded categories are defined.
  • The contract preserves the permanent exclusion of person-related data.
  • The contract addresses partial reads, permissions, unsupported endpoints, recursion, and backwards compatibility.
  • Group and event examples demonstrate how the contract is applied.
  • Follow-up implementation issues can apply the decision to individual resource types.
  • feat: support group member fields as group-scoped managed resources #135 links to this decision and does not silently decide the project-wide default on its own.

Relationship to #135

#135 can continue to implement group member fields with the current explicit option while this design decision is pending. Whether --with-member-fields becomes the default should be resolved here by the project owner.

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

    triageUnsorted intake — decide in the weekly sweep

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions