Repository navigation
meta: the manual-surface audit only greps OpenAPI, so it cannot discover legacy write paths — it produced 60 claims, several already proven wrong #111
Description
#108, #109 and #110 are three instances of one bug. This issue is about the bug that produced them.
The defect
docs/runbook-manual-surface.md defines the manual surface as an API gap:
CT does not expose a write endpoint (or any endpoint) … Nothing in
ctcan close this until CT ships one
and its re-audit procedure (:132-141) says to re-check by grepping the OpenAPI spec for additional
methods on the path.
That procedure can only ever discover REST endpoints. ChurchTools' admin UI writes a large amount of
master data through the legacy POST /index.php?q=churchdb/ajax func=saveMasterData interface, which
appears in no OpenAPI spec. So the audit is structurally incapable of finding the very thing it
concludes does not exist — and it concludes "permanent", "never", "no API at all" on that basis.
The irony is that ct-cli already depends on the legacy surface it does not audit: the permission
catalog is generated from POST /index.php?q=churchauth/ajax func=getMasterData
(src/permissions/README.md:7-13). The evidence that the audit is incomplete has been in the repo
the whole time.
What it produced
A sweep of both repos found 60 "cannot be managed" claims. Classified by the evidence each one
cites:
- REST-only (a 404 / absent spec path): the suspect class. Confirmed wrong so far —
Bereiche (feat(resources): Bereiche/departments ARE writable via the legacy master-data endpoint — make them a managed resource #108, asserted in 8+ places), person statuses (feat(resources): person statuses are not declarable — thestatuspermission domain is only half-portable #96's premise, also already contradicted
by this repo's owndocs/api-coverage.md:32), security levels (bug(permissions): "security-level ids are universal" is an assumption, not a guarantee — they are editable master data #110). - unsourced (no evidence at all): e.g. "
cc_securitylevel… values are not resources at all"
(src/permissions/scope.ts:66-68,src/permissions/types.ts:23-29,src/permissions/adopt.ts:294).
cc_securitylevelis an editable master-data table. - structural (a real invariant): people/memberships (
src/engine/guard.ts:10-19), other modules,
hierarchy, the deliberate group-field exclusions. These are correct and should be relabelled so
they stop being confused with the above.
The wording is the harmful part. "ChurchTools has NO REST catalog" is true and useful. "Permanently,
not provisionally" (eqrm/ct-structure ct.config.ts:22-30), "can never be declared, adopted or
created" (src/resolve/refs.ts:101-112), "not resources at all" — these are unsupported by the
evidence offered, and they are what stopped anyone re-checking for three months.
Asks
- Fix the audit procedure so it cannot miss the legacy surface. Every "no write API" verdict
should require both: (a) the REST/OpenAPI probe, and (b) a check of
getMasterData→data.masterDataTablesfor a matching table, and, where neither settles it,
(c) a browser capture of the admin UI performing the action. - Re-label the claim taxonomy. Distinguish "no REST endpoint" (a capability fact about one API)
from "out of mandate" (a product decision) from "impossible" (a claim that now needs both probes
to earn). Most existing text conflates all three. - Down-scope the absolutes. "Permanently", "never", "no API at all" should not appear unless
both probes were run and recorded, with dates. - Record the probe in the doc, the way the permission-catalog note already does — so the next
reader can tell a verified negative from an inherited assumption.
Acceptance
- The re-audit procedure includes the master-data registry and a UI-capture step.
- Existing "no write API" claims are re-checked against it, and each is marked verified-negative
(with date and method) or corrected. - Mandate decisions are worded as decisions, not as API limits.
Related: #108, #109, #110, #96, #102. Full 60-claim inventory with file:line for each is available
in the caller's session and can be pasted here on request.
Activity
Merge pull request #112 from eqrm/feat/issues-106-110-111
2000game commentedon Aug 14, 2026
Shipped in #112 (merged 2026-08-14). A "no write API" verdict now requires both the REST/OpenAPI probe and a
getMasterData → masterDataTablesprobe, plus a UI capture where neither settles it, and a record of which probes ran when. The three buckets are relabelled so a capability fact, a roadmap item and a product decision no longer read alike, and the wrong claims were down-scoped across the runbook, api-coverage.md, both handbook pages and the code comments. Seedocs/runbook-manual-surface.md.(Not auto-closed: the PR body's
Closes **#111**bolding defeats GitHub's keyword parser.)