Skip to content

docs: manual-surface runbook — what ChurchTools cannot (yet) automate (#26) - #42

Merged
2000game merged 1 commit into
mainfrom
docs/manual-surface-runbook-26
Jul 9, 2026
Merged

2000game merged 1 commit into
mainfrom
docs/manual-surface-runbook-26

Conversation

@2000game

@2000game 2000game commented Jul 9, 2026

Copy link
Copy Markdown
Member

Adds docs/runbook-manual-surface.md: the manual surface an operator must handle by hand, so #23's selective adoption can be scoped deliberately.

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.

…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
2000game merged commit b2cc1dc into main Jul 9, 2026
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
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.

docs: manual-surface runbook — what ChurchTools cannot (yet) automate

1 participant