Skip to content

A right absent from the host's catalog should warn, not hard-error — it makes a portable config unusable across instances #178

Description

@2000game

Summary

ct plan hard-errors when a config declares a right that is not in the active permission catalog. For an estate whose instances genuinely have different modules installed, that makes a single host-portable config impossible — the config can be valid on one host and fatal on another, with no way to express the difference.

Request: downgrade this to a skip-with-warning, matching how ct already treats the mirror case.

The asymmetry

ct already handles the other direction gracefully. A live grant whose authId is absent from the catalog is reported and left alone:

! group_role #1920 ("implementierung_churchtools_mitglied"): a live grant carries
  authId 2066, which is not in the permission catalog — left untouched (never
  revoked). Capture this instance's own catalog (`ct permissions catalog --refresh`)
  if this right should be manageable.

That is the right posture: say what you cannot manage, manage the rest. But the reverse — a declared right the catalog does not define — aborts the whole plan:

✗ ct.config.ts:2338 — group_role "implementierung_churchtools_mitglied":
  "preserveUnknown" names a scope dimension no right in the permission catalog
  scopes by: crp_query. A dimension that matches nothing would preserve nothing and
  read exactly like "there was nothing to preserve" — check the spelling against
  `ct get permissions-catalog`.

One declaration that does not apply to this host takes down planning for everything that does.

How we hit it

eqrm/ct-structure is one config applied to two instances. Dev had no per-instance capture, so it silently resolved every right through ct-cli's bundled catalog — a snapshot taken from prod. Under that borrowed catalog, prod-only rights resolved fine on dev and the config looked portable.

Capturing dev's own catalog made it truthful, and the config stopped planning there. 13 of the 113 declared rights do not exist on dev:

Rights Why dev lacks them
jpmFlowManager:* (10) Flow is not installed on dev
churchreport:view, churchreport:view query Report module is not installed on dev
churchreport:edit masterdata deleted by ChurchTools in 3.136.2 — a genuine config bug, fixed separately

The first 12 are not errors. They are correct on prod and inapplicable on dev.

Note the trap: the config was never portable, but nothing could tell us, because the missing capture masked it. Capturing the catalog — which ct itself prescribes — is what surfaced the breakage.

Why not the obvious workarounds

  • Environment conditionals in the config. Defeats the point of one declarative file, and this repo deliberately has none.
  • Drop the module rights. Surrenders management of rights that are live and correct on prod.
  • Install the modules on dev. Best fidelity, but licensing and instance changes are not always available, and ct should not require two instances to be identical to plan against both.

Proposed behaviour

When a declared right, or a preserveUnknown dimension, is absent from the active catalog:

  • emit a warning naming the right, the group_role, and the host's catalog version
  • skip that grant for this host, never planning it as a grant or a revoke
  • keep planning everything else
  • keep --detailed-exitcode semantics unchanged (a skip is not a pending change)

Reserve the hard error for the case it was written for: a right absent from every catalog ct knows, which is a typo or a deleted right rather than a host difference. A flag (--strict-catalog) could restore today's behaviour for anyone who wants planning to fail on any unresolvable declaration.

Environment

  • ct-cli 3.6.x (bundled catalog: ChurchTools 3.134.0, 187 rights)
  • prod eqrm.church.tools — ChurchTools 3.136.2, 187 rights
  • dev eqrm-dev.church.tools — ChurchTools 3.137.0-RC13, 221 rights

Related: 18 authIds in the 2050–2078 range denote different rights on the two hosts, since CT allocates custom-module ids per instance in install order. Declaring by string key keeps that safe today, and this request does not change it — but it is the reason per-instance captures must be adopted, which is what exposed this bug.

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