Skip to content

fix: reject malformed --url, correct TTY detection, document mixed-case re-login - #115

Merged
leet-c1 merged 1 commit into
mainfrom
fix/url-tty-keychain-housekeeping
Sep 3, 2026
Merged

fix: reject malformed --url, correct TTY detection, document mixed-case re-login#115
leet-c1 merged 1 commit into
mainfrom
fix/url-tty-keychain-housekeeping

Conversation

@leet-c1

@leet-c1 leet-c1 commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Three small, independent housekeeping fixes (ledger C108, C106, C97). Each is surgical and self-contained; no shared behavior changes beyond the one guard helper.

C108 — ParseURL rejects a malformed host instead of building a nonsense base URL

The degenerate fallback accepted any input and prepended https://, so https://, //, ://host, or a host with an embedded space/control char became base URLs like https://https:// that only failed later, far from the input. One shared isHostShaped guard now requires a fallback host to be non-empty and free of spaces, control characters, and /; anything else is a usage error (exit 2) naming the source. The main (url.Parse-succeeds) path is unchanged.

  • Live-validated against a tenant: https://, ://host, //, ac me.conductor.one, https://ho st each exit 2 with … is not a valid host …; a valid host and a mixed-case host both exit 0 and return rows.
  • New TestParseURLRejectsMalformedFallbackHost; the existing degenerate-path test was repointed to an input that still reaches the fallback-with-warning (…@ho%zzst.example) so the credential-drop warning path stays covered. Both mutation-proven (fail before, pass after).

C106 — isTerminal() no longer treats /dev/null as a TTY

os.ModeCharDevice is set for /dev/null too, so a redirected auth login with no URL tried to prompt instead of returning the url is required usage error. Switched to term.IsTerminal(int(os.Stdin.Fd())) (the TTY ioctl). New TestIsTerminalFalseForDevNull (fails on the old code).

C97 — document the mixed-case---url re-login remedy at the point of use

Host lower-casing shipped in v0.4.0, so a credential stored by a pre-v0.4.0 build under a mixed-case keychain key is no longer found. The remedy (re-run auth login) was already in the v0.4.0 changelog but not surfaced anywhere at the point of failure — now added to auth login --help. A true auto-migration would need the pre-lowercase host threaded through the client constructor API, which is out of scope for a housekeeping change; documented instead.

Checks

build, vet, go test -count=1, -shuffle=on, golangci-lint (0), gosec (0), gitleaks (clean), govulncheck (clean), go mod tidy idempotent (adds golang.org/x/term). Two independent reviews (full + delta) — the only finding was the C97 version boundary, fixed.

🤖 Generated with Claude Code

…e-login

Three small housekeeping fixes:

- C108: ParseURL's degenerate fallback accepted any input and prepended
  "https://", building nonsense base URLs ("https://https://", "https:////",
  "://host", embedded space/control char) that failed later, far from the
  input. A fallback host must now be non-empty and free of spaces, control
  characters, and "/"; anything else is a usage error (exit 2) naming the
  source. One shared isHostShaped guard, not per-shape special cases.

- C106: isTerminal() classified /dev/null as a TTY (it is a character device),
  so a redirected `auth login` with no URL tried to prompt instead of returning
  the "url is required" usage error. Switched to term.IsTerminal, which issues
  the TTY ioctl that tells them apart.

- C97: a credential stored under a mixed-case --url before the host-lowercasing
  fix is no longer found (the keychain key is now lower-cased). True auto-
  migration needs the pre-lowercase host threaded through the client API, which
  is out of scope here; documented the re-login remedy in `auth login --help`
  and the CHANGELOG instead.

Both defects are mutation-proven by their tests (fail before, pass after) and
C108 was live-validated against a tenant: five garbage shapes exit 2, valid and
mixed-case URLs still work.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@leet-c1
leet-c1 merged commit 29bbcff into main Sep 3, 2026
2 checks passed
leet-c1 added a commit that referenced this pull request Sep 3, 2026
A full audit of every tracked .md file against the current command/help surface
and recent PRs (#103-#117) found gaps where a shipped change had not reached one
or more docs. No behavioral defects and no branding/identifier leaks were found;
these are documentation-only fixes.

HIGH:
- cmd/agents.md: document the v0.6.0 BREAKING envelope-unwrap in "Reading
  output" — typed `get` prints the resource flat (`.id`, not `.app.id`), naming
  a wrapper key in `--fields` exits 2, and `mcp servers get` has only
  `connectorId`. README already covered this; the agent-facing doc did not.
- README.md: add the `docs search` no-relevance-threshold caveat (#117), which
  had reached help + `docs agents` but not README.
- CHANGELOG.md: merge the duplicated `### Added`/`### Changed` headers in
  [Unreleased] into one block each (Added/Changed/Fixed); all 14 entries
  preserved verbatim.

MED:
- README.md: `policies` step_kinds/baseline_policy_id + the auto-approval jq
  recipe (#103); `mcp servers register --user-id` and the flags settable at
  register time.
- cmd/agents.md: `mcp tools approve` takes multiple ids in one process (#116).
- CLAUDE.md: document the shared repeatable-flag registrar convention (#111).

LOW:
- README.md: `--tool-id` caps (100/32), requestable-connectors non-pagination,
  `entitlements create --resource-type` default CUSTOM, `requests create
  --duration` is Go-style vs the protobuf-duration flags.
- cmd/agents.md + skill: malformed-`--url` rejection (#115).
- CLAUDE.md: negative `--limit`/`--page-size` rejection + page-size clamp.
- .claude/commands/c1i.md: add `auth token`, the ~/.c1i.yaml wrong-tenant
  stderr warning, a pointer to the command groups, and the docs-search caveat.

Every claim verified against `--help` or live behavior; embedded `docs agents`
re-checked to render the new content. Build/vet/test/shuffle/lint/gosec/gitleaks
/govulncheck all clean.

Co-authored-by: leet-c1 <264029741+leet-c1@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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