Repository navigation
feat(device-client): native client with sign-up, sign-in, re-login - #126
Merged
Merged
Conversation
…ountGone, tighter store and body checks
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
First of three PRs for
orbyn-device-client, the native async client the Engineering app uses to be a device of an Orbyn account. Design note:docs/device-client.md. MIT OR Apache-2.0, no dependency on any app, builds onorbyn-auth-client,orbyn-cryptoandorbyn-contracts.DeviceApi(one call;HttpApiis the real one),KeyStore(the OS keychain in the app;MemoryStorefor tests) andClock.DeviceClient<A, S, C>holds them.KeyStoreholds only the device keys, the account and device ids with the email, the session token and a vault key (32 random bytes made on the device; the host seals its own snapshot under it). The zone-key cache lives in the host's sealed snapshot, not here. Nothing secret is in aDebugprint or an error.PendingSignUpthat holds the keys in memory only, and the emailed code with a resend. No request body holds the password or an encoding of it.reauthenticate(password)answersReauthenticationRequired(engine#120) with the ordinary login as a trusted start from the same device key: no new route, no approval, a recent session; then the caller retries.sign_out(forget)andsign_out_all().ReauthenticationRequired,InvalidCode,RateLimited { retry_after },DeletionScheduled,AccountGone(a 401 plusPOST /v1/accounts/status),SessionExpired,TooLarge, and more; none carries a secret or a URL.httpsonly excepthttpto a loopback IP literal, 30 s timeout, 32 MiB body cap.is_loopback_literalis public for the app's LocalOnly gate.scripts/local.shgetsinvite-code(prints only a fresh invite code) andlatest-code <email>(prints only the newest email code), documented indocs/local.md.02f1075):AccountGoneonly whenPOST /v1/accounts/statusanswers 200 with a deletion time (the app destroys key material on it). A 401 with the account alive, or a status call that fails or answers non-200, isSessionExpired; tests for each, and nothing is wiped.RequestandResponseprint their method, path or status and the body's length only, never the body; their bodies are wiped on drop. A test checksDebugand{:#?}hold none of the body bytes.Content-Length;with_body_limitlowers it).verify_sign_upre-checks the store before the code is sent, so a sign-in finished in between is not overwritten and the code is not spent;latest-codematches the address at the end of the message.applabel (engine#73).Closes #
Testing
tests/client.rs: the client against an in-memory engine that runs the real OPAQUE server side and checks the real signatures (14 tests: invite, proof of work, code, trusted start, second factor, re-login after 11 minutes, account gone against a session ended elsewhere, rate limit, redirects not followed,Retry-After,Debughygiene, vault key, body limit).tests/local_stack.rs(ignored by default): against the real engine onscripts/local.sh up: invite, sign-up with the code from the worker log, a second pending device, a wrong password, the re-login and sign-out everywhere. Passes.AccountGoneon any status answer or when the status call fails,Retry-After, the reauthentication mapping,forget, the busy-store checks at sign-up, verify and sign-in, vault key kept across accounts, redirects followed,Debugprinting the body (response and request), no running body limit. All killed except one equivalent: the earlyContent-Lengthcheck only saves reading, since the running limit stops the same response.cargo test --workspace.Co-authors
none
AI usage
Checklist
docs/architecture.mdwith any rule change; generated wire types with any contract change