Skip to content

feat(auth): capture ChurchTools host at login (no hardcoded default) - #16

Merged
2000game merged 2 commits into
mainfrom
feat/auth-host
Jul 8, 2026
Merged

2000game merged 2 commits into
mainfrom
feat/auth-host

Conversation

@2000game

@2000game 2000game commented Jul 8, 2026

Copy link
Copy Markdown
Member

Captures the ChurchTools host at login instead of leaning on a hardcoded prod default.

Follow-up to the host concern raised while verifying #15 (Phase 4). Stacked on feat/phase-4-apply-destroy — retarget to main once #15 merges.

What changes

  • ct auth login --host <url> --token <token> — the host is verified and stored with the token (bound together) in the macOS Keychain as one JSON blob.
  • resolveConfig is now async and resolves the host as: CT_HOST env → stored login host → error (run ct auth login --host …). No hardcoded eqrm.church.tools default — the generic tool no longer ships one org's host.
  • CtClient no longer defaults its config (callers pass it); all command call sites await resolveConfig().
  • auth status / logout updated for the host+token credential.

Behaviour

$ ct plan                       # no CT_HOST, no stored login
✗ No ChurchTools host configured. Run `ct auth login --host <url> --token <token>` (or set CT_HOST).

$ ct auth login                 # no host
✗ No host provided. Pass --host <url> or set CT_HOST.

Migration

The credential is stored under a new Keychain entry with a JSON {host, token} value; a legacy bare-token value is rejected by parseCredentials. Re-run ct auth login --host <url> --token <token> once after upgrading.

Testing

140 tests pass. New: resolveConfig precedence (env > stored > error, injectable reader) and parseCredentials (valid / legacy-bare-token / missing-field). Verified read-only: the no-host refusal, login requiring host then token, and --host in --help. tsc / eslint / build clean.

https://claude.ai/code/session_017tFJu7SrS5uLdit5FtXiwS

The host is now bound to the login: captured via `ct auth login --host <url>`
(or CT_HOST) and stored with the token in the Keychain as one JSON blob.
resolveConfig is async and resolves host from CT_HOST env → stored login, with
no fallback — commands fail with a clear 'run ct auth login --host' message
instead of silently targeting the eqrm prod default.

- tokenStore: storeCredentials/readCredentials/clearCredentials ({host, token});
  parseCredentials rejects legacy bare-token values (requires re-login).
- config: async resolveConfig(env, readHost) + normalizeHost; injectable for tests.
- CtClient no longer defaults its config (callers pass it).
- auth login gains -H/--host; status/logout updated.
- Tests: config precedence + parseCredentials; adopt test sets CT_HOST.

Migration: re-run `ct auth login --host <url> --token <token>` once.
@2000game
2000game changed the base branch from feat/phase-4-apply-destroy to main July 8, 2026 09:27
…n entry, simplify status guard

- session.ts: 'Not logged in' hint now includes the required --host
- tokenStore: clearCredentials also deletes the pre-host 'login-token' entry so an upgrade never orphans a secret
- auth status: reuse readToken() instead of re-implementing its env→stored precedence
@2000game
2000game merged commit 98ee39b into main Jul 8, 2026
1 check passed
@2000game
2000game deleted the feat/auth-host branch July 8, 2026 09:56
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.

1 participant