Skip to content

feat: add complete permission reports - #133

Merged
2000game merged 7 commits into
eqrm:mainfrom
bwl21:feat/permission-reports
Aug 25, 2026
Merged

2000game merged 7 commits into
eqrm:mainfrom
bwl21:feat/permission-reports

Conversation

@bwl21

@bwl21 bwl21 commented Aug 20, 2026 •

Copy link
Copy Markdown
Contributor

Summary

  • add a complete, read-only ChurchTools permission dataset covering person, status, group-type-role, and concrete group-role domains
  • add subject-oriented and object-oriented Markdown reports from the same collected live dataset
  • preserve non-declarable permission dimensions and direct person grants without changing adopt grants semantics
  • retain ChurchTools labels losslessly, including significant leading or trailing whitespace
  • group non-empty subject reports by deterministic permission-set fingerprints containing both names and IDs
  • share one validated churchauth/ajax getMasterData decoder between permission reports and catalog capture
  • support one-pass output through --by-subject, --by-object, and --by-both

Empty subjects

  • empty status (ST) and group-type-role (GTRL) subjects are shown explicitly under Keine Berechtigungen, without a misleading hash, because they reveal actionable permission gaps
  • person (PRS) and concrete group-role (GRRL) subjects are included only when they have at least one direct permission; listing every empty person and role pairing would hide relevant gaps among thousands of irrelevant rows
  • inherited effective person permissions are not synthesized into direct person permission sets

CLI

ct report permissions --by-subject [file]
ct report permissions --by-object [file]
ct report permissions --by-both <base>

For example:

ct report permissions --by-both reports/permission-report.md
# reports/permission-report_by-subject.md
# reports/permission-report_by-object.md

Both reports are generated from one authenticated, read-only collection pass. Generated reports/ output is ignored by Git because it may contain instance-specific data and person names.

Validation

  • npm test — 964 passed, 5 skipped
  • npm run typecheck
  • npm run lint
  • npm run format:check
  • npm run build
  • documentation staleness check
  • git diff --check
  • live read-only report generation against a ChurchTools instance
  • Apple Silicon standalone-binary smoke test

Fixes #142

@bwl21
bwl21 marked this pull request as ready for review August 20, 2026 19:54
@2000game

Copy link
Copy Markdown
Member

Hey, vielen Dank für das gute Telefonat vorhin! Dazu hier noch ein paar Fragen und Anmerkungen zum PR.

1. Versionsnummer

package.json steht hier auf 3.0.0-bwl, package-lock.json zieht mit. Die Version wird in diesem Repo von semantic-release verwaltet, deshalb bitte beides auf den Stand von main zurücksetzen. Das eigentliche Problem mit dem hartcodierten .version("0.0.0") in src/index.ts ist real, gehört aber zu #116 und nicht hierher.

2. Legacy-Parität können wir streichen

Der Punkt, über den ich am längsten nachgedacht habe: Auf unserer Seite gibt es keine historischen PHP-Permission-Reports. Der Katalog wird beim ersten Lauf von ct-cli selbst aufgebaut, es existiert also gar nichts, wogegen hier jemand diffen könnte — außer bei dir lokal.

Damit kostet die Parität Aufwand ohne Nutzen, und der md5("[]")-Sonderfall in hash.ts führt sogar in die Irre: Die Fingerprints leerer Permission-Sets stimmen zwischen altem und neuem Report überein, alle nicht-leeren unterscheiden sich aber ohnehin (steht ja auch so in der PR-Beschreibung). Wer die beiden Reports nebeneinanderlegt, zieht daraus genau den falschen Schluss.

Konkret: Sonderfall bitte raus. Entweder das leere Set wie jedes andere hashen oder — schöner — für leere Sets gar keinen Fingerprint ausgeben und stattdessen ein explizites (keine Berechtigungen) schreiben. Und den Abschnitt "Legacy parity" aus der PR-Beschreibung und aus docs/handbuch/permissions.md nehmen.

Die Aufnahmeregeln würde ich dagegen behalten, nur anders begründen: leere ST- und GTRL-Subjekte immer listen, damit Lücken sichtbar werden, PRS und GRRL dagegen nur bei tatsächlich vorhandenen Direktberechtigungen — das ist für sich genommen eine sinnvolle Reporting-Regel, unabhängig davon, was das alte Tool gemacht hat.

3. .gitignore

Die Ergänzungen überschneiden sich mit denen in #134. Lass uns die in genau einem PR landen.

4. Frage zu collect.ts

src/reports/permissions/collect.ts normalisiert dasselbe churchauth/ajax getMasterData-Payload, das src/permissions/catalog-store.ts schon liest. Gegen den Legacy-Endpoint selbst habe ich nichts, der ist hier bewusst als schmale Tür angelegt. Aber zwei unabhängige Normalisierungspfade auf dasselbe Payload driften über kurz oder lang auseinander. Siehst du eine gemeinsame Struktur, die sich beide teilen können?

Ansonsten: read-only, keine Änderung an adopt/plan/apply und die generierten Reports aus der Versionierung raus — genau richtig so.

@bwl21

bwl21 commented Aug 24, 2026

Copy link
Copy Markdown
Contributor Author

Addressed the review in dcf9a70:

  • reset the package version was already part of the previous main merge
  • removed the legacy empty-set hash special case; empty ST/GTRL entries are now rendered explicitly as (keine Berechtigungen) without a fingerprint
  • documented and tested the independent inclusion rule: empty statuses and group-type roles expose actionable permission gaps, while listing every empty person and concrete group-role pairing would hide those gaps in irrelevant output
  • kept only the report-specific /reports/ ignore entry; removed the unrelated IDE/release additions
  • extracted the shared, validated churchauth/ajax getMasterData decoder used by both catalog capture and permission reports
  • updated the PR description and handbook accordingly

Validation: 964 tests passed (5 skipped) on the PR branch, plus typecheck, lint, format check, build, docs staleness, and git diff --check. The local integration branch with #139 also passes all checks (978 tests passed, 5 skipped).

…a reads

Review follow-ups on eqrm#133:

- `ct report permissions` creates its output directories. The documented
  invocation writes into `reports/`, which this branch gitignores and
  which does not exist in a fresh clone, so the command ran the full
  live collection and then died with a raw ENOENT.
- `fetchChurchAuthMasterData` falls back per FIELD again, not per
  envelope. `response.data ?? response` rejected a payload split across
  `data` and the top level, which the code it replaced accepted.
- A duplicate authId warns and keeps the first definition instead of
  throwing. `ct permissions catalog --refresh` is the only way to act
  on a staleness warning and must degrade, not die, on an instance
  whose plugin set aliases a right under two modules.
- The subject report sorts each hash group's rights and drops exact
  duplicates. The bullet de-duplication only collapsed adjacent
  repeats, so a subject whose rows for one right were not contiguous
  got the same right several times, each with a subset of its objects.
  The report is now independent of API row order and diff-stable.
- docs/handbuch/permissions.md declares src/reports/permissions/** and
  src/commands/report.ts as sources, so the staleness gate covers the
  code it documents, and records the new row ordering.

Claude-Session: https://claude.ai/code/session_01SaAzHDgDPSvLnfkKcnDj37
@2000game
2000game merged commit bf4d92b into eqrm:main Aug 25, 2026
3 checks passed
@bwl21
bwl21 deleted the feat/permission-reports branch August 26, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: add read-only permission reports

2 participants