feat(keystone): add persistent user identity and access - #175
Conversation
|
@robonix-ci test |
❌ robonix CI — job failure after scenarios (17/17 scenarios passed, 100%)Webots job concluded
Report: open HTML report. |
Add the canonical Keystone IDL and capability contracts, persistent account and voiceprint storage, bootstrap administrator lifecycle, and direct Atlas registration through the shared lifecycle driver. Integrate authenticated text, voice, and hands-free access through Liaison, launch Keystone as an rbnx builtin, and configure the Webots deployment for external Client discovery. Assisted-by: Codex:gpt-5.6
Pass the deployment Keystone endpoint to Liaison so authenticated voice sessions cannot fall back to the disabled legacy access gate. Keep Webots account data in a robot-owned path across checkout changes and cover the launch mapping with a regression test. Assisted-by: Codex:gpt-5.6
kaileliu
left a comment
There was a problem hiding this comment.
The identity model, persistence safeguards, and Liaison integration are coherent, and the focused CI coverage is substantial. Approving this direction; the two inline notes are non-blocking follow-ups to tighten distributed voiceprint consistency and make the network trust boundary unambiguous.
| .find(|user| user.user_id == input.target_user_id) | ||
| .ok_or_else(|| Status::not_found("target user does not exist"))?; | ||
| if target.voiceprint_enrolled { | ||
| self.delete_external_voiceprint(&target.user_id, "").await?; |
There was a problem hiding this comment.
Non-blocking follow-up: the external Voiceprint deletion happens before store.admin_delete_user enforces the final-enabled-admin invariant. Deleting the last admin therefore removes the external enrollment, then returns permission_denied while Keystone still records the user as enrolled. Please validate the local mutation before the external side effect, or add compensation that restores a consistent binding on local rejection.
| use serde::Deserialize; | ||
|
|
||
| pub const DEFAULT_ATLAS_ENDPOINT: &str = "127.0.0.1:50051"; | ||
| pub const DEFAULT_LISTEN: &str = "0.0.0.0:50095"; |
There was a problem hiding this comment.
Non-blocking follow-up: this public bind conflicts with the README guidance to keep Keystone private and use a Liaison proxy; Liaison explicitly does not proxy these account RPCs, and the Webots manifest also exposes this port for direct client access. Please align the documentation and default, and document the transport/trust boundary for session tokens if direct remote access is the intended design.
Summary
Add Keystone as a boot-managed Robonix system component and connect persistent user identity to Liaison, Voiceprint, Pilot task submission, hands-free voice sessions,
rbnx chat, and Robonix Client.Why
Robonix previously had no durable account authority. A client-provided user hint could not prove which account was acting, voiceprint enrollment was not bound to a signed-in account, and administrative policy had no protected control plane.
What changed
robonix/lifecycle/driver;rbnxbuilt-in system component and include it in install, clean, deploy, and package-run paths;Security boundary
Clients discover Keystone through Atlas and connect to its generated capability endpoints. Session tokens are random opaque values; only their SHA-256 hashes are stored. Passwords use Argon2. A client-supplied user ID is never accepted as authentication.
This PR does not add Sentinel policy enforcement.
Validation
cargo fmt --all -- --check— passed;cargo test -p robonix-keystone— 9 tests passed;cargo test -p robonix-liaison— 15 tests passed;cargo test -p robonix-cli— 24 tests passed;cargo clippy -p robonix-keystone -p robonix-liaison -p robonix-cli --all-targets -- -D warnings— passed;Dependencies
The matching Client integration is
syswonder/robonix-client#6.This PR targets
devand keeps the existingdev-keystonereview branch.