feat(reborn): minimal multi-user local auth — StaticUserTokenAuthenticator (#5272)#5286
feat(reborn): minimal multi-user local auth — StaticUserTokenAuthenticator (#5272)#5286zetyquickly wants to merge 1 commit into
Conversation
…cator (#5272) A `WebuiAuthenticator` that maps several bearer user-tokens to distinct `(UserId, UserRole)` pairs, so one operator can act as several users — `director@` (Admin), `Bob` / `Carol` (Member), shared `engineering@` (Member) — by swapping the bearer token. Unlike `EnvBearerAuthenticator` (single token -> single operator), the resolved `UserRole` travels with the authentication, so the role-gated admin surface (#5268) and the per-(tenant, user) dispatch principal (#5267) both work per token. - `StaticUserTokenAuthenticator::from_json` parses an `IRONCLAW_REBORN_USER_TOKENS` JSON array of `{token, user_id, role}` rows (`role` defaults to least-privilege Member). - Constant-time, non-short-circuiting token comparison (no content/position timing leak); rejects empty table / empty token / invalid user_id / bad JSON. - `mounts_operator_webui_config_routes() == false` — deployment-wide operator config stays with the separate operator credential (per the composition guardrail); admin-ness is carried by the role, not operator capabilities. Local-dev / standalone only; production multi-user uses Session/OIDC. The turn-runner already isolates each caller's threads per-turn via `ThreadScopeResolver::resolve_for_turn`, so multiple users through one process are supported at the scope layer; wiring this authenticator into the `serve` command (env selection + base-owner handling) is the follow-on integration. Tests: 5 unit tests (token->user+role mapping, role default, unknown/empty/ prefix rejection, invalid-config rejection, no operator routes). Crate green under `--all-features` clippy `-D warnings`. Part of #5261. Depends on #5266 (UserRole on the caller). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. 🗂️ Base branches to auto review (2)
Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Comment |
|
🚅 Deployed to the ironclaw-pr-5286 environment in ironclaw-ci-preview
|
|
Superseded by the REST-user rework (issue #5272, redesigned). The env-token StaticUserTokenAuthenticator + IRONCLAW_REBORN_USER_TOKENS path is dropped in favor of REST-created users (durable LocalUserDirectoryStore + admin POST/GET/DELETE /admin/users + PUT /role, returning a one-time bearer). The replacement lands on #5270 (control plane). Closing per epic #5261 de-nest. |
What
Implements #5272 — the prerequisite that lets one operator act as several users on localhost, so per-user capability policy can be driven by hand.
StaticUserTokenAuthenticator(aWebuiAuthenticator, inironclaw_reborn_webui_ingress) maps several bearer user-tokens to distinct(UserId, UserRole)pairs. Swap the bearer token → becomedirector@(Admin),Bob/Carol(Member), or sharedengineering@(Member). UnlikeEnvBearerAuthenticator(single token → single operator), the resolvedUserRoletravels with the authentication, so the role-gated admin surface (#5268) and the per-(tenant, user)dispatch principal (#5267) both work per token.from_jsonparses anIRONCLAW_REBORN_USER_TOKENSJSON array of{token, user_id, role}rows (roleacceptsowner/admin/member, defaults tomember).EnvBearerAuthenticator.user_id, and malformed JSON.mounts_operator_webui_config_routes() == false— deployment-wide operator config stays with the separate operator credential (per the composition guardrail: multi-user authenticators don't grantoperator_webui_config). Admin-ness is carried by the role, consumed by [capability-policy] Admin REST surface (four dimensions) + REST action catalog #5268'sis_admin()gate.Multi-user is not blocked
The turn-runner already resolves thread scope per-turn from the actor (
ThreadScopeResolver::resolve_for_turn;owner_scoped_thread_scope_isolates_each_callerlocks that each caller gets its ownowners/<user>subtree). So multiple users through oneserveprocess are supported at the scope layer — this authenticator supplies the per-request identity + role.Scope / follow-on
This PR ships the authenticator primitive (the issue's core). Wiring it into the
ironclaw-reborn servecommand — selecting it fromIRONCLAW_REBORN_USER_TOKENS, and handling the base runtime owner + session-signing-secret (today both derived from the single env token) — is a separable integration step, deliberately kept out of this PR to avoid destabilizing the existing single-user serve path. That wiring lands with the manual-test enablement.Tests
5 unit tests: token → user+role mapping, role-default, unknown/empty/prefix rejection, invalid-config rejection, no operator routes. Crate green under
cargo clippy -p ironclaw_reborn_webui_ingress --all-features --tests -- -D warningsand the full--all-featurestest suite.Stacking
Stacked on #5266 (PR #5270, base
feat/reborn-user-role) — that PR putUserRoleon the WebChat-v2 caller /WebuiAuthentication. Part of epic #5261.🤖 Generated with Claude Code