docs: manual-surface runbook — what ChurchTools cannot (yet) automate (#26) - #42
Merged
Merged
Conversation
…mented vs out of scope (#26) Evidence-based inventory of what ct cannot (yet) automate, cross-checked against registry.ts, context.ts, synthetic.ts, permissions/, docs/api-coverage.md, and issue #26's own known-manual-surface table, so instance bootstrap (#23) can scope selective adoption deliberately instead of guessing. - API gap (CT exposes no write endpoint): group member-statuses, meeting points, permission name<->authId catalog. - Not yet implemented (tracked issues #20, #21, #22, #25): campus assignment, group field decision table, portable/logical references, environments, domainId-by-reference, grant adoption, catalog lifecycle. - Out of tool scope (permanent, by design): people/memberships, other CT modules, module-level settings/custom fields/i18n. Includes a manual regeneration procedure for the permission catalog, a re-audit procedure for new CT releases (the OpenAPI spec is self-trimming), and a checklist for bringing a new instance to parity. Linked from README's status list.
2000game
added a commit
that referenced
this pull request
Aug 24, 2026
#116, #117) (#146) * fix: report the real version and the running binary for --version (#116) `--version` was the literal `.version("0.0.0")`, identical for a released install and a locally linked dev build. That is worse than a missing version: it reads like evidence, and in one downstream repo it sent the next person chasing a PATH problem that did not exist. The version is now baked in from package.json at build time — `tsup` and `bun build --compile` both inline the JSON import — and printed alongside the resolved entry path, so `ct --version` answers "which version" and "which ct" at once: 1.7.0 (/usr/local/bin/ct) Inside a standalone binary `import.meta.url` points into bun's embedded filesystem, which bun's `fs` shim reports as existing; that prefix is recognised so the binary's own path on disk is shown instead. Baking the version in makes the artifacts version-sensitive at BUILD time, which the release pipeline has to respect: the binaries are now recompiled in semantic-release's prepare step, after the version bump, for the same reason the tarball is already packed there (#84). Otherwise every released binary would report the repo's 0.1.0 placeholder. Both jobs call one shared build-binaries.sh so the two invocations cannot drift. Fixes #116 Claude-Session: https://claude.ai/code/session_018JShVZYNLaRb4hF5KbHCXG * feat(auth): ask "who am I?" per environment (#117) `plan`, `apply`, `adopt`, `get`, `coverage`, `state`, `refresh` and `permissions` all take `-e, --env <name>`; `auth status` did not, so the one command whose entire job is answering "which account is this?" could only ever answer it for the default host. Finding out which identity `--env dev` would use meant running something that touches the host for real, or reading ct.envs.json and the Keychain by hand. - `ct auth status --env <name>` resolves that env's host and reports the identity there. The host goes to stderr, so `| jq` still sees only the identity JSON. - `ct auth status --all` checks every environment in ct.envs.json — one line each, with where the token came from and nothing of the token itself: dev https://mychurch-dev.church.tools ✓ Ada Lovelace (#42) via Keychain prod https://mychurch.church.tools ✗ no token It exits non-zero if any environment has no working token, so CI can gate on it before an apply. A failing env is reported as that env's line rather than aborting the run, so one unreachable instance cannot hide the others. - `ct auth logout --env <name>` clears just that host's credentials and leaves other logins in place (the default blob goes too when it holds a copy of the same token, so no secret is orphaned). Token resolution mirrors authedSession exactly — profile `tokenEnv` → CT_LOGINTOKEN → the host-keyed Keychain entry — so a green line means the same command with `--env` will authenticate the same way. The stored lookup is host-keyed, so one env can never report another env's identity. Read-only throughout: the only network call is the whoami handshake, and only for an env that has a token to try. Fixes #117 Claude-Session: https://claude.ai/code/session_018JShVZYNLaRb4hF5KbHCXG * fix(auth,release): address review findings on #116/#117 `ct auth status --all` walks every host in ct.envs.json, so the bare `CT_LOGINTOKEN` fallback fanned one instance's token out to all of them — as a `login_token=` query parameter, into every instance's access log — and then reported a green line for envs nothing was configured for. The ambient token is now offered only to the host it is bound to (`CT_HOST`, else the stored default login's host); everything else reports no token. Failures are rendered with `formatError`, so the HTTP status a real `CtApiError` carries survives — 401, 403 and 500 no longer render alike. Token resolution moved inside the try, so a credential store that throws reports that env instead of aborting the sweep, and the preflight now runs `assertMinVersion` too, so a green line cannot be followed by an apply that refuses on the instance version. `ct auth logout --env <name>` still drops the default blob when it holds a copy of the same token — but it now says so, instead of promising that other logins are untouched while commands without `--env` lose their host. Release: the shipped binaries were the only ones never executed — they are recompiled in semantic-release's prepare step, after the smoke jobs ran, on an unpinned `bun-version: latest`. Both jobs now pin the same bun, the recompiled linux binary is smoke-tested again in the release job, and the smoke script asserts `ct --version`, which nothing in CI had ever run on the compiled path. The version constant is injected via `define` (tsup + `bun build`) instead of a default JSON import esbuild cannot tree-shake, which was inlining the whole manifest — devDependencies, scripts, dependency list — into the published bundle; running from source falls back to reading package.json. Finally, cli-version compared a decoded path against a percent-encoded one, which fails for any checkout path needing escaping. Claude-Session: https://claude.ai/code/session_018JShVZYNLaRb4hF5KbHCXG * style: prettier Claude-Session: https://claude.ai/code/session_018JShVZYNLaRb4hF5KbHCXG
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds
docs/runbook-manual-surface.md: the manual surface an operator must handle by hand, so #23's selective adoption can be scoped deliberately.assertNotPeople, other CT modules, module settings).Docs-only; suite green (263 passed / 4 skipped), lint clean. Reviewed by the orchestrator (content cross-checked against registry, DSL, permissions module, and docs/api-coverage.md claims).
Closes #26.