feat: port Client and loopback OAuth from wavekat-cli#2
Merged
Conversation
Work plan for getting from the empty scaffold on main to a usable v0.0.1 on crates.io: what to port from wavekat-cli, the public surface, dep set, file layout, test plan, and the open design questions to settle before code lands. Companion to wavekat-voice/docs/13-platform-login-and-client.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Land the v0.0.1 surface from docs/01-initial-port.md: storage-agnostic Client, two-phase loopback OAuth handshake (crate returns the URL, caller opens it), Token newtype with redacted Debug, thiserror-typed Error, and the Me/whoami + revoke_current_token typed methods. Carries over the unit tests verbatim from wavekat-cli (base64url RFC vectors, random_state shape, html_escape) and adds tests for Token redaction, Error::Http format, HandshakeOptions::default, and the loopback_handshake URL shape. Includes examples/smoke.rs for the manual smoke test against a live platform. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror the prefix rename happening in wavekat-platform PR #116. The crate doesn't hardcode the prefix in functional code (the Token newtype splits on `_` for its redacted Debug), but tests, docs, and examples all referenced the old prefix. The CLAUDE.md guidance is also updated — it previously said "don't rename, the prefix is just a string"; that's true once users have stored credentials in the wild, but we're explicitly doing it now because there are no real users yet. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Mirror the wire-format change in wavekat-platform: the loopback flow
now sends `?client=<short>[&source=<host>]` instead of a single
`?name=<short> on <host>`. Lets the platform's consent UI render the
two parts separately and lets future token-management UIs sort or
group by app independent of which machine the token was minted from.
API changes (breaking, but nothing has consumed v0.0.1 yet):
- `HandshakeOptions::client_name: Option<String>` →
`HandshakeOptions::client: Option<String>` (defaults to
`"wavekat-platform-client"`)
+ `HandshakeOptions::source: Option<String>` (defaults to the
machine hostname)
+ `HandshakeOptions::omit_source: bool` (privacy escape hatch for
desktop apps that don't want to disclose the hostname).
Tests: explicit client+source override, omit-source path, default-
falls-back-to-hostname. All 16 unit tests + 1 doctest pass; clippy
+ fmt clean.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Merged
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.
Summary
Lands the v0.0.1 surface from
docs/01-initial-port.md(which is included in this PR — supersedes #1 after the branch rename).Client::new(base_url, token)+whoami()/revoke_current_token()and the lower-levelget_json/post_json/delete/put_proxy_bytes/put_presigned_bytes/get_stream_tohelpers.loopback_handshakereturns aPendingHandshake { url(), state(), wait().await }. The crate does not open browsers — caller decides (webbrowser::openfor CLI,shell.openExternalfor desktop,println!for remote).Tokennewtype with redactedDebug(keepswkcli_prefix, hides the rest), noDisplay.thiserrortypedError(Http / Network / Decode / StateMismatch / Cancelled / Timeout / BadRequest / Io) +Resultalias.Me { id, login, name, email, role }.examples/smoke.rsfor the manual smoke test (login / whoami / revoke).thiserror. MSRV pinned to 1.75.Test plan
cargo check --workspace --all-targetscargo test --workspace— 14 unit tests + 1 doctest pass (includesbase64url_rfc_vectors,random_state_shape,html_escape_handles_metacharactersported verbatim fromwavekat-cli, plus new tests for Token redaction,Error::Httpformat,HandshakeOptions::default, andloopback_handshakeURL shape).cargo clippy --workspace --all-targets -- -D warningsclean.cargo fmt --all -- --checkclean.cargo doc --no-deps -p wavekat-platform-client --all-featuresbuilds.platform.wavekat.comper the plan:cargo run --example smoke -- logincargo run --example smoke -- whoami --token \$TOKENcargo run --example smoke -- revoke --token \$TOKEN🤖 Generated with Claude Code