Files
openclaw/docs/.generated/config-baseline.counts.json
Peter Steinberger 53dcaaedec feat(gateway): generic operator roles for non-maintainer access (#128548)
* feat(gateway): generic operator roles for non-maintainer access

Adds gateway.roles: named role bundles over a closed capability set —
sessions.others (none/view/suggest/write), an agents allowlist, and an
operator-scope ceiling. Roles are person-level (additive user_profiles.role
column, SQLite stays at v9); users.setRole (admin-only) assigns them. With
no gateway.roles config, behavior is unchanged for solo deployments.

Enforcement is deny-by-default from a host-minted actor identity
(system vs operator+profileId on server-only client.internal, never
accepted from the wire) and covers every entry point: WS RPCs, OpenAI-compat
and Responses HTTP, tools invocation, cron, questions, usage, task
suggestions, session catalog/sharing/reads. The agents allowlist gates both
session creation and run-start on existing sessions. Subagent completion
announce and descendant wake mint explicit system authority so role
boundaries never silently drop parent notifications.

The enforcement surface is expressed through a narrow policy vocabulary
(operatorSessionCap, hasOperatorBoundary, authorizeSessionSharing) rather
than per-handler policy internals.

* fix(gateway): heal PR CI after rebase onto main

- Break import cycles: extract GatewayOperatorRoleActor leaf contract; merge
  session-group-mutation-targets into session-sharing-target-input.
- Split sessions-suggestions.test.ts (max-lines) into a visibility suite.
- Add users.setRole to the 2026.8 train registry test and regenerate the
  Kotlin protocol client.
- Startup UNAVAILABLE gating now precedes session authorization: session
  stores are not loaded during startup, so authorization reads would deny
  with a misleading non-retryable error.
- sessions.assignOwner keeps its documented visibility-authorized contract
  when no operator role caps the caller; view/suggest-capped roles still
  cannot reassign foreign session ownership.
- Test stubs updated for main's socket readyState guard (#128144) and the
  system-authority arg on channel-native resets.

* test(gateway): chat.send pending-profile dispatch carries its required session target

chat.send requires a non-empty sessionKey at the protocol level; the mutation
pipeline now rejects targetless frames before profile-dependent dispatch, so
the pending-profile test must send a realistic frame.
2026-08-24 01:20:03 -07:00

6 lines
56 B
JSON

{
"core": 2355,
"channel": 3584,
"plugin": 3957
}