fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies (#110225)

* fix(onboarding): leave session.dmScope unset so the personal-agent default "main" applies

* chore(onboarding): document deliberate dmScope personal-agent default

* docs(security): align formal-verification dmScope claim with the personal-agent default
This commit is contained in:
Peter Steinberger
2026-07-18 03:54:45 +01:00
committed by GitHub
parent cd1ab40632
commit ff9cb0f679
7 changed files with 11 additions and 14 deletions

View File

@@ -197,7 +197,7 @@ By default, OpenClaw routes all DMs into the main session for cross-device conti
| `per-account-channel-peer` | Like above, split further by account (multi-account channels). |
| `per-peer` | Each sender gets one session across all channels of the same type. |
Local CLI onboarding writes `session.dmScope: "per-channel-peer"` when unset, and preserves any explicit existing value.
Local CLI onboarding preserves an explicit `session.dmScope` and otherwise leaves it unset, so the `"main"` default applies: all direct messages across channels share the agent's rolling main session (the personal-agent default). For shared or multi-user inboxes, set `session.dmScope: "per-channel-peer"`; `openclaw security audit` recommends isolation when it detects multi-user DM traffic.
This is a messaging-context boundary, not a host-admin boundary. If users are mutually adversarial and share the same Gateway host/config, run separate gateways per trust boundary instead.

View File

@@ -238,7 +238,7 @@ Typical fields in `~/.openclaw/openclaw.json`:
- `agents.defaults.model` / `models.providers` (if Minimax chosen)
- `tools.profile` (local onboarding defaults to `"coding"` when unset; existing explicit values are preserved)
- `gateway.*` (mode, bind, auth, tailscale)
- `session.dmScope` (local onboarding defaults this to `"per-channel-peer"` when unset; existing explicit values are preserved. Details: [CLI Setup Reference](/start/wizard-cli-reference#outputs-and-internals))
- `session.dmScope` (onboarding preserves explicit values and otherwise leaves it unset, so the `"main"` default keeps all direct messages across channels in the agent's rolling main session—the personal-agent default. For shared or multi-user inboxes, use `"per-channel-peer"`; `openclaw security audit` recommends isolation when it detects multi-user DM traffic. Details: [CLI Setup Reference](/start/wizard-cli-reference#outputs-and-internals))
- `channels.telegram.botToken`, `channels.discord.token`, `channels.matrix.*`, `channels.signal.*`, `channels.imessage.*`
- Channel DM allowlists when you opt in during the channel prompts. Discord, Matrix, Microsoft Teams, and Slack resolve names to IDs when possible; other channels take IDs directly (for example numeric Telegram sender IDs or WhatsApp phone numbers).
- `skills.install.nodeManager`

View File

@@ -123,7 +123,7 @@ Follow-on models that tighten fidelity around real-world failure modes: non-atom
### Routing dmScope precedence and identityLinks
**Claim:** routing keeps DM sessions isolated by default and only collapses sessions when explicitly configured, via channel precedence and identity links. Channel-specific `dmScope` overrides win over global defaults; `identityLinks` collapse sessions only within explicit linked groups, not across unrelated peers.
**Claim:** `dmScope` precedence and identity links behave deterministically: the default `main` scope shares one rolling session across a single owner's DMs (the personal-agent default), while any configured isolating scope (`per-peer`, `per-channel-peer`, `per-account-channel-peer`) keeps DM sessions strictly separated. Channel-specific `dmScope` overrides win over global defaults; `identityLinks` collapse sessions only within explicit linked groups, not across unrelated peers. Multi-user inboxes are expected to opt into an isolating scope (the runtime security audit recommends this when it detects multi-user DM traffic).
| Result | Targets |
| -------------- | ------------------------------------------------------------------------- |

View File

@@ -325,7 +325,7 @@ Typical fields in `~/.openclaw/openclaw.json`:
- `agents.defaults.model` / `models.providers` (if Minimax chosen)
- `tools.profile` (local onboarding defaults to `"coding"` when unset; existing explicit values are preserved)
- `gateway.*` (mode, bind, auth, tailscale)
- `session.dmScope` (local onboarding defaults this to `per-channel-peer` when unset; existing explicit values are preserved)
- `session.dmScope` (onboarding preserves explicit values and otherwise leaves it unset, so the `main` default keeps all direct messages across channels in the agent's rolling main session—the personal-agent default. For shared or multi-user inboxes, use `per-channel-peer`; `openclaw security audit` recommends isolation when it detects multi-user DM traffic)
- `channels.telegram.botToken`, `channels.discord.token`, `channels.matrix.*`, `channels.signal.*`, `channels.imessage.*`
- Channel allowlists (Discord, iMessage, Signal, Slack, Telegram, WhatsApp) when you opt in during prompts; Discord and Slack also resolve entered names to IDs
- `skills.install.nodeManager`

View File

@@ -113,7 +113,7 @@ flow and skip that prompt.
- Gateway port **18789**
- Gateway auth **Token** (auto-generated, even on loopback)
- Tool policy: `tools.profile: "coding"` for new setups (an existing explicit profile is preserved)
- DM isolation: `session.dmScope: "per-channel-peer"` for new setups. Details: [CLI setup reference](/start/wizard-cli-reference#outputs-and-internals)
- DM sessions: onboarding preserves an explicit `session.dmScope` and otherwise leaves it unset, so the `"main"` default keeps all direct messages across channels in the agent's rolling main session—the personal-agent default. For shared or multi-user inboxes, use `"per-channel-peer"`; `openclaw security audit` recommends isolation when it detects multi-user DM traffic. Details: [CLI setup reference](/start/wizard-cli-reference#outputs-and-internals)
- Tailscale exposure **Off**
- Telegram and WhatsApp DMs default to **allowlist**: Telegram asks for a numeric Telegram user ID, WhatsApp asks for a phone number

View File

@@ -4,11 +4,12 @@ import type { OpenClawConfig } from "../config/config.js";
import { applyLocalSetupWorkspaceConfig } from "./onboard-config.js";
describe("applyLocalSetupWorkspaceConfig", () => {
it("sets secure dmScope default when unset", () => {
it("leaves dmScope unset when not configured", () => {
const baseConfig: OpenClawConfig = {};
const result = applyLocalSetupWorkspaceConfig(baseConfig, "/tmp/workspace");
expect(result.session?.dmScope).toBe("per-channel-peer");
expect(result.session?.dmScope).toBeUndefined();
expect(result).not.toHaveProperty("session.dmScope");
expect(result.gateway?.mode).toBe("local");
expect(result.agents?.defaults?.workspace).toBe("/tmp/workspace");
expect(result.tools?.profile).toBe("coding");

View File

@@ -1,15 +1,15 @@
/** Shared config mutations used by interactive and non-interactive onboarding. */
import { setConfigValueAtPath } from "../config/config-paths.js";
import type { DmScope } from "../config/types.base.js";
import type { OpenClawConfig } from "../config/types.openclaw.js";
import type { ToolProfileId } from "../config/types.tools.js";
/** Default DM scoping selected during local onboarding. */
const ONBOARDING_DEFAULT_DM_SCOPE: DmScope = "per-channel-peer";
/** Default tool profile selected during local onboarding. */
const ONBOARDING_DEFAULT_TOOLS_PROFILE: ToolProfileId = "coding";
/** Applies local gateway/workspace defaults without overwriting explicit user defaults. */
// Deliberately writes no session.dmScope: the schema default "main" (one rolling
// personal-agent session across channels) is the product default. Multi-user DM
// isolation is opt-in; `openclaw security audit` nudges it when traffic warrants.
export function applyLocalSetupWorkspaceConfig(
baseConfig: OpenClawConfig,
workspaceDir: string,
@@ -27,10 +27,6 @@ export function applyLocalSetupWorkspaceConfig(
...baseConfig.gateway,
mode: "local",
},
session: {
...baseConfig.session,
dmScope: baseConfig.session?.dmScope ?? ONBOARDING_DEFAULT_DM_SCOPE,
},
tools: {
...baseConfig.tools,
profile: baseConfig.tools?.profile ?? ONBOARDING_DEFAULT_TOOLS_PROFILE,