Skip to content

feat(keystone): add persistent user identity and access - #175

Draft
enkerewpo wants to merge 2 commits into
devfrom
dev-keystone
Draft

feat(keystone): add persistent user identity and access#175
enkerewpo wants to merge 2 commits into
devfrom
dev-keystone

Conversation

@enkerewpo

@enkerewpo enkerewpo commented Jul 22, 2026

Copy link
Copy Markdown
Member

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

  • define the canonical Keystone IDL and capability contracts in the shared Robonix capability tree;
  • add a SQLite-backed Keystone service with WAL mode, foreign keys, Argon2 password hashes, opaque revocable sessions, roles, account enablement, and per-user voice guard policy;
  • bootstrap the first administrator from an explicit environment password or a randomly generated mode-0600 one-time credentials file;
  • preserve users, roles, sessions, policy, and voiceprint bindings across process restarts;
  • add registration, login, logout, profile/password management, voiceprint binding and preview, and administrator RPCs;
  • prevent deletion, disablement, or demotion of the final enabled administrator, including concurrent updates;
  • register Keystone and its capabilities in Atlas, including the repository-level shared robonix/lifecycle/driver;
  • launch Keystone as an rbnx built-in system component and include it in install, clean, deploy, and package-run paths;
  • resolve authenticated text and voice turns to the canonical Keystone user before submitting to Pilot;
  • enforce voice guard by matching the signed-in account's bound Voiceprint identity;
  • require an authenticated session for hands-free control when Keystone is configured;
  • extend Liaison voice-session and hands-free IDL with the opaque session token;
  • keep deployments without a configured Keystone endpoint backward compatible;
  • configure the Webots deployment for Atlas discovery by external clients.

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;
  • Debian 13 WorkPC full Webots boot — 14 components active, including Keystone, Executor, Liaison, Scene, Speech, Voiceprint, Mapping, and Navigation;
  • restart persistence — an existing account and session remained valid after a full-stack restart;
  • macOS Client to WorkPC Robonix — connection, signup, login, profile, administrator authorization, role and voice-guard changes, authenticated text submission, audio routing, microphone capture, and speaker playback passed;
  • stored voiceprint preview — the signed-in account retrieved its saved PCM sample and the client rendered and played it;
  • authorization — a normal user was denied administrator RPCs.

Dependencies

The matching Client integration is syswonder/robonix-client#6.

This PR targets dev and keeps the existing dev-keystone review branch.

@github-actions github-actions Bot added comp:keystone system/keystone comp:docs docs/ and READMEs type:feature New feature (feat:) labels Jul 22, 2026
@github-actions github-actions Bot added comp:liaison system/liaison comp:rbnx tools/rbnx comp:capabilities capabilities/ contracts labels Jul 24, 2026
@enkerewpo enkerewpo changed the title feat(keystone): add identity and access core feat(keystone): add persistent user identity and access Jul 24, 2026
@enkerewpo
enkerewpo marked this pull request as ready for review July 25, 2026 16:39
@enkerewpo
enkerewpo requested a review from kaileliu as a code owner July 25, 2026 16:39
@enkerewpo

Copy link
Copy Markdown
Member Author

@robonix-ci test

@github-actions

github-actions Bot commented Jul 25, 2026

Copy link
Copy Markdown

❌ robonix CI — job failure after scenarios (17/17 scenarios passed, 100%)

Webots job concluded failure after producing a scenario summary. Treat this as a failed CI run; inspect lifecycle, teardown, report, and raw logs in the action run.

suite scenario result rounds
builtin fault_recovery_builtin 3
builtin file_roundtrip 1
builtin plan_control_builtins 1
builtin run_command 1
cap camera_snapshot 1
cap explore_smoke 2
cap lidar_snapshot 1
cap mapping_save 1
cap memgraph_failure_lesson 1
cap memgraph_roundtrip 3
cap memory_roundtrip 1
cap scene_object_fixture 1
cap speech_speak 1
cap voiceprint_list 1
flow fault_recovery 4
flow object_navigation 4
flow patrol_observe 3

Report: open HTML report.
Action run: open GitHub Actions run.
Raw logs: scenario JSONL, provider logs, simulator logs, final caps, and boot logs are in the same artifact.

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
@enkerewpo
enkerewpo marked this pull request as draft August 8, 2026 04:03

@kaileliu kaileliu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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?;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:capabilities capabilities/ contracts comp:docs docs/ and READMEs comp:keystone system/keystone comp:liaison system/liaison comp:rbnx tools/rbnx type:feature New feature (feat:)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants