Skip to content

meta: the manual-surface audit only greps OpenAPI, so it cannot discover legacy write paths — it produced 60 claims, several already proven wrong #111

Closed

Description

@2000game

#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 ct can 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:

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

  1. 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.masterDataTables for a matching table, and, where neither settles it,
    (c) a browser capture of the admin UI performing the action.
  2. 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.
  3. Down-scope the absolutes. "Permanently", "never", "no API at all" should not appear unless
    both probes were run and recorded, with dates.
  4. 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

  1. added a commit that references this issue on Aug 14, 2026
  2. 2000game commented on Aug 14, 2026

    @2000game
    MemberAuthor

    Shipped in #112 (merged 2026-08-14). A "no write API" verdict now requires both the REST/OpenAPI probe and a getMasterData → masterDataTables probe, 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. See docs/runbook-manual-surface.md.

    (Not auto-closed: the PR body's Closes **#111** bolding defeats GitHub's keyword parser.)

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