Commit Graph

19140 Commits

Author SHA1 Message Date
Albertzzzhu d2523affe7
Merge a19f3890b8 into c4265a5f16 2026-03-15 14:43:44 +00:00
ShengtongZhu a19f3890b8 fix(guardian): remove unused import, align pi-ai version with root
- Remove unused PluginRuntime import, consolidate import lines
- Bump @mariozechner/pi-ai from 0.55.3 to 0.58.0 to match root

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 22:43:38 +08:00
Ayaan Zaidi c4265a5f16
fix: preserve Telegram word boundaries when rechunking HTML (#47274)
* fix: preserve Telegram chunk word boundaries

* fix: address Telegram chunking review feedback

* fix: preserve Telegram retry separators

* fix: preserve Telegram chunking boundaries (#47274)
2026-03-15 18:10:49 +05:30
Andrew Demczuk 26e0a3ee9a
fix(gateway): skip Control UI pairing when auth.mode=none (closes #42931) (#47148)
When auth is completely disabled (mode=none), requiring device pairing
for Control UI operator sessions adds friction without security value
since any client can already connect without credentials.

Add authMode parameter to shouldSkipControlUiPairing so the bypass
fires only for Control UI + operator role + auth.mode=none. This avoids
the #43478 regression where a top-level OR disabled pairing for ALL
websocket clients.
2026-03-15 13:03:39 +01:00
助爪 5c5c64b612
Deduplicate repeated tool call IDs for OpenAI-compatible APIs (#40996)
Merged via squash.

Prepared head SHA: 38d8048359
Co-authored-by: xaeon2026 <264572156+xaeon2026@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-15 19:46:07 +08:00
ShengtongZhu e55c4c4044 fix(guardian): resolve well-known provider baseUrl from pi-ai model database
When a provider (e.g. anthropic, openai) is not explicitly configured in
openclaw.json, fall back to pi-ai's built-in model database to resolve
baseUrl and api type. This avoids requiring users to manually configure
well-known providers.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 19:33:14 +08:00
Jason 9d3e653ec9
fix(web): handle 515 Stream Error during WhatsApp QR pairing (#27910)
* fix(web): handle 515 Stream Error during WhatsApp QR pairing

getStatusCode() never unwrapped the lastDisconnect wrapper object,
so login.errorStatus was always undefined and the 515 restart path
in restartLoginSocket was dead code.

- Add err.error?.output?.statusCode fallback to getStatusCode()
- Export waitForCredsSaveQueue() so callers can await pending creds
- Await creds flush in restartLoginSocket before creating new socket

Fixes #3942

* test: update session mock for getStatusCode unwrap + waitForCredsSaveQueue

Mirror the getStatusCode fix (err.error?.output?.statusCode fallback)
in the test mock and export waitForCredsSaveQueue so restartLoginSocket
tests work correctly.

* fix(web): scope creds save queue per-authDir to avoid cross-account blocking

The credential save queue was a single global promise chain shared by all
WhatsApp accounts. In multi-account setups, a slow save on one account
blocked credential writes and 515 restart recovery for unrelated accounts.

Replace the global queue with a per-authDir Map so each account's creds
serialize independently. waitForCredsSaveQueue() now accepts an optional
authDir to wait on a single account's queue, or waits on all when omitted.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* test: use real Baileys v7 error shape in 515 restart test

The test was using { output: { statusCode: 515 } } which was already
handled before the fix. Updated to use the actual Baileys v7 shape
{ error: { output: { statusCode: 515 } } } to cover the new fallback
path in getStatusCode.

Co-Authored-By: Claude Code (Opus 4.6) <noreply@anthropic.com>

* fix(web): bound credential-queue wait during 515 restart

Prevents restartLoginSocket from blocking indefinitely if a queued
saveCreds() promise stalls (e.g. hung filesystem write).

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: clear flush timeout handle and assert creds queue in test

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: evict settled credsSaveQueues entries to prevent unbounded growth

Co-Authored-By: Claude <noreply@anthropic.com>

* fix: share WhatsApp 515 creds flush handling (#27910) (thanks @asyncjason)

---------

Co-authored-by: Jason Separovic <jason@wilma.dog>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 17:00:07 +05:30
Ted Li 843e3c1efb
fix(whatsapp): restore append recency filter lost in extensions refactor, handle Long timestamps (#42588)
Merged via squash.

Prepared head SHA: 8ce59bb715
Co-authored-by: MonkeyLeeT <6754057+MonkeyLeeT@users.noreply.github.com>
Co-authored-by: scoootscooob <167050519+scoootscooob@users.noreply.github.com>
Reviewed-by: @scoootscooob
2026-03-15 03:03:31 -07:00
Ace Lee d7ac16788e
fix(android): support android node `calllog.search` (#44073)
* fix(android): support android node  `calllog.search`

* fix(android): support android node calllog.search

* fix(android): wire callLog through shared surfaces

* fix: land Android callLog support (#44073) (thanks @lxk7280)

---------

Co-authored-by: lixuankai <lixuankai@oppo.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 14:54:32 +05:30
Frank Yang 4bb8a65edd
fix: forward forceDocument through sendPayload path (follow-up to #45111) (#47119)
Merged via squash.

Prepared head SHA: d791190f83
Co-authored-by: thepagent <262003297+thepagent@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-15 17:23:53 +08:00
Sahan 9616d1e8ba
fix: Disable strict mode tools for non-native openai-completions compatible APIs (#45497)
Merged via squash.

Prepared head SHA: 20fe05fe74
Co-authored-by: sahancava <57447079+sahancava@users.noreply.github.com>
Co-authored-by: frankekn <4488090+frankekn@users.noreply.github.com>
Reviewed-by: @frankekn
2026-03-15 16:36:52 +08:00
Onur Solmaz a2d73be3a4
Docs: switch README logo to SVG assets (#47049) 2026-03-15 08:58:45 +01:00
SkunkWorks0x c33375f843
docs: replace outdated Clawdbot references with OpenClaw in skill docs (#41563)
Update 5 references to the old "Clawdbot" name in
skills/apple-reminders/SKILL.md and skills/imsg/SKILL.md.

Co-authored-by: imanisynapse <imanisynapse@gmail.com>
2026-03-15 08:29:19 +01:00
Praveen K Singh d230bd9c38
Docs: fix stale Clawdbot branding in agent workflow file (#46963)
Co-authored-by: webdevpraveen <webdevpraveen@users.noreply.github.com>
2026-03-15 08:01:03 +01:00
Ayaan Zaidi 6a458ef29e
fix: harden compaction timeout follow-ups 2026-03-15 12:13:23 +05:30
Jason f77a684131
feat: make compaction timeout configurable via agents.defaults.compaction.timeoutSeconds (#46889)
* feat: make compaction timeout configurable via agents.defaults.compaction.timeoutSeconds

The hardcoded 5-minute (300s) compaction timeout causes large sessions
to enter a death spiral where compaction repeatedly fails and the
session grows indefinitely. This adds agents.defaults.compaction.timeoutSeconds
to allow operators to override the compaction safety timeout.

Default raised to 900s (15min) which is sufficient for sessions up to
~400k tokens. The resolved timeout is also used for the session write
lock duration so locks don't expire before compaction completes.

Fixes #38233

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* test: add resolveCompactionTimeoutMs tests

Cover config resolution edge cases: undefined config, missing
compaction section, valid seconds, fractional values, zero,
negative, NaN, and Infinity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add timeoutSeconds to compaction Zod schema

The compaction object schema uses .strict(), so setting the new
timeoutSeconds config option would fail validation at startup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: enforce integer constraint on compaction timeoutSeconds schema

Prevents sub-second values like 0.5 which would floor to 0ms and
cause immediate compaction timeout. Matches pattern of other
integer timeout fields in the schema.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: clamp compaction timeout to Node timer-safe maximum

Values above ~2.1B ms overflow Node's setTimeout to 1ms, causing
immediate timeout. Clamp to MAX_SAFE_TIMEOUT_MS matching the
pattern in agents/timeout.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: add FIELD_LABELS entry for compaction timeoutSeconds

Maintains label/help parity invariant enforced by
schema.help.quality.test.ts.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: align compaction timeouts with abort handling

* fix: land compaction timeout handling (#46889) (thanks @asyncjason)

---------

Co-authored-by: Jason Separovic <jason@wilma.dog>
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 12:04:48 +05:30
Vincent Koc 8e04d1fe15
macOS: restrict canvas agent actions to trusted surfaces (#46790)
* macOS: restrict canvas agent actions to trusted surfaces

* Changelog: note trusted macOS canvas actions

* macOS: encode allowed canvas schemes as JSON
2026-03-14 23:26:19 -07:00
Vincent Koc 3cbf932413
Tlon: honor explicit empty allowlists and defer cite expansion (#46788)
* Tlon: fail closed on explicit empty allowlists

* Tlon: preserve cited content for owner DMs
2026-03-14 23:24:53 -07:00
Vincent Koc d1e4ee03ff fix(context): skip eager warmup for non-model CLI commands 2026-03-14 23:20:15 -07:00
Jinhao Dong 8e4a1d87e2
fix(openrouter): silently dropped images for new OpenRouter models — runtime capability detection (#45824)
* fix: fetch OpenRouter model capabilities at runtime for unknown models

When an OpenRouter model is not in the built-in static snapshot from
pi-ai, the fallback hardcodes input: ["text"], silently dropping images.

Query the OpenRouter API at runtime to detect actual capabilities
(image support, reasoning, context window) for models not in the
built-in list. Results are cached in memory for 1 hour. On API
failure/timeout, falls back to text-only (no regression).

* feat(openrouter): add disk cache for OpenRouter model capabilities

Persist the OpenRouter model catalog to ~/.openclaw/cache/openrouter-models.json
so it survives process restarts. Cache lookup order:

1. In-memory Map (instant)
2. On-disk JSON file (avoids network on restart)
3. OpenRouter API fetch (populates both layers)

Also triggers a background refresh when a model is not found in the cache,
in case it was newly added to OpenRouter.

* refactor(openrouter): remove pre-warm, use pure lazy-load with disk cache

- Remove eager ensureOpenRouterModelCache() from run.ts
- Remove TTL — model capabilities are stable, no periodic re-fetching
- Cache lookup: in-memory → disk → API fetch (only when needed)
- API is only called when no cache exists or a model is not found
- Disk cache persists across gateway restarts

* fix(openrouter): address review feedback

- Fix timer leak: move clearTimeout to finally block
- Fix modality check: only check input side of "->" separator to avoid
  matching image-generation models (text->image)
- Use resolveStateDir() instead of hardcoded homedir()/.openclaw
- Separate cache dir and filename constants
- Add utf-8 encoding to writeFileSync for consistency
- Add data validation when reading disk cache

* ci: retrigger checks

* fix: preload unknown OpenRouter model capabilities before resolve

* fix: accept top-level OpenRouter max token metadata

* fix: update changelog for OpenRouter runtime capability lookup (#45824) (thanks @DJjjjhao)

* fix: avoid redundant OpenRouter refetches and preserve suppression guards

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 11:48:39 +05:30
ShengtongZhu 474a41a3ee fix(guardian): use openclaw/plugin-sdk/core instead of monolithic import
Bundled plugins must use scoped plugin-sdk imports (e.g. /core, /compat)
instead of the monolithic openclaw/plugin-sdk entry point.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:11:46 +08:00
ShengtongZhu 9fbbc97e9a fix(guardian): use runtime.modelAuth instead of runtime.models
Align with main's PluginRuntime interface: use `modelAuth` (not `models`)
for API key resolution. Remove dependency on `resolveProviderInfo` (not
available on main) — provider info is now resolved from config at
registration time via `resolveModelFromConfig`.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 14:06:59 +08:00
Vincent Koc a97b9014a2
External content: sanitize wrapped metadata (#46816) 2026-03-14 23:06:30 -07:00
ShengtongZhu 400787110c fix: restore core files to match main (rebase artifact cleanup)
The rebase left stale versions of src/plugin-sdk/index.ts,
src/agents/model-auth.ts, src/plugins/runtime/*, and
src/cli/daemon-cli/lifecycle.test.ts. These are not guardian changes —
restore them to match origin/main exactly.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 13:47:28 +08:00
Peter Steinberger 8851d06429
docs: reorder unreleased changelog 2026-03-14 22:16:41 -07:00
ShengtongZhu 39b0ae7cc1 chore(guardian): update pnpm-lock.yaml for guardian extension
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:47:54 +08:00
ShengtongZhu 2e2eed339a refactor(guardian): replace async instruction extraction with full system prompt caching
Remove the LLM-based standingInstructions and availableSkills extraction
pipeline. Instead, cache the main agent's full system prompt on the first
llm_input and pass it as-is to the guardian as "Agent context".

This eliminates two async LLM calls per session, simplifies the codebase
(~340 lines removed), and gives the guardian MORE context (the complete
system prompt including tool definitions, memory, and skills) rather than
a lossy LLM-extracted summary.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:33:28 +08:00
ShengtongZhu 8f0c1cb85f docs(guardian): add model selection guidance to README
Recommend instruction-following models (sonnet, haiku, gpt-4o-mini) and
warn against coding-specific models that tend to ignore the strict
ALLOW/BLOCK output format.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 8a2c15f9bc fix(guardian): detect system triggers from historyMessages, not just currentPrompt
Heartbeat prompts may arrive via historyMessages (as the last user message)
rather than via currentPrompt, depending on the agent loop stage. Check both
sources for system trigger detection so heartbeat tool calls are consistently
skipped regardless of how the prompt is delivered.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 13b4a0bbeb fix(guardian): preserve isSystemTrigger across agent loop continuations
During a heartbeat cycle, llm_input fires multiple times: first with the
heartbeat prompt (isSystemTrigger=true), then without a prompt as the agent
loop continues after tool results. Previously the flag was unconditionally
rewritten on each llm_input, resetting to false when currentPrompt was
undefined — causing heartbeat tool calls to reach the guardian LLM
unnecessarily.

Now preserves the existing isSystemTrigger value when currentPrompt is
empty/undefined, and only resets it when a real user message arrives.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 31ed78ef28 fix(guardian): remove trailing comma in plugin manifest JSON
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu f4488a73ff fix(guardian): stricter ALLOW/BLOCK verdict parsing in guardian response
Require a delimiter (colon, space, or end of line) after ALLOW/BLOCK keywords.
Previously `startsWith("ALLOW")` would match words like "ALLOWING" or
"ALLOWANCE", potentially causing a false ALLOW verdict if the model's
response started with such a word.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 8972213aee docs(guardian): improve README with quick start, default config values, and block behavior
- Replace Enable/Config sections with Quick start (bundled plugin, no npm install)
- Show all default values in config example
- Add "When a tool call is blocked" section explaining user flow
- Remove Model selection section
- Fix dead anchor link

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-15 12:32:47 +08:00
ShengtongZhu 6a3220b0c6 feat(guardian): enhance context awareness and add conversation summarization
- Add rolling conversation summary generation to provide long-term context without token waste
- Extract standing instructions and available skills from system prompt for better decision context
- Support thinking block extraction for reasoning model responses (e.g. kimi-coding)
- Add config options for context tools, recent turns, and tool result length
- Implement lazy context extraction with live message array reference
- Skip guardian review for system triggers (heartbeat, cron)
- Improve error handling for abort race conditions and timeout scenarios
- Normalize headers in model-auth to handle secret inputs consistently
- Update documentation with comprehensive usage guide and security model
2026-03-15 12:32:47 +08:00
Albert 7be93f981b fix(guardian): include trailing assistant messages in conversation context
When the main model is iterating autonomously (tool call → response →
tool call → ...) without new user input, assistant messages after the
last user message were being discarded. The guardian couldn't see what
the model had been doing, leading to potential misjudgments.

Now trailing assistant messages are appended to the last conversation
turn, giving the guardian full visibility into the model's recent
actions and reasoning during autonomous iteration.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:32:34 +08:00
Albert 1c6b5d7b72 refactor(guardian): use pi-ai completeSimple, improve prompt and logging
- Replace 3 raw fetch() API call functions (OpenAI, Anthropic, Google)
  with a single pi-ai completeSimple() call, ensuring consistent HTTP
  behavior (User-Agent, auth, retry) with the main model
- Remove authMode field — pi-ai auto-detects OAuth from API key prefix
- Rewrite system prompt for strict single-line output format, add
  "Do NOT change your mind" and "Do NOT output reasoning" constraints
- Move decision guidelines to system prompt, add multi-step workflow
  awareness (intermediate read steps should be ALLOWed)
- Simplify user prompt — remove inline examples and criteria
- Use forward scanning in parseGuardianResponse for security (model's
  verdict appears first, attacker-injected text appears after)
- Add prominent BLOCK logging via logger.error with full conversation
  context dump (████ banner, all turns, tool arguments)
- Remove 800-char assistant message truncation limit
- Increase default max_user_messages from 3 to 10

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:32:34 +08:00
Albert ba28dbc016 feat(guardian): add LLM-based intent-alignment guardian plugin
Guardian intercepts tool calls via before_tool_call hook and sends them
to a separate LLM for review — blocks actions the user never requested,
defending against prompt injection attacks.

Key design decisions:
- Conversation turns (user + assistant pairs) give guardian context to
  understand confirmations like "yes" / "go ahead"
- Assistant replies are explicitly marked as untrusted in the prompt to
  prevent poisoning attacks from propagating
- Provider resolution uses SDK (not hardcoded list) with 3-layer
  fallback: explicit config → models.json → pi-ai built-in database
- Lazy resolution pattern for async provider/auth lookup in sync register()

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-15 12:32:34 +08:00
Ayaan Zaidi 37c79f84ba
fix(android): theme popup surfaces 2026-03-15 09:48:08 +05:30
Sebastian Schubotz db20141993
feat(android): add dark theme (#46249)
* Android: add mobile dark theme

* Android: fix remaining dark mode card surfaces

* Android: address dark mode review comments

* fix(android): theme onboarding flow

* fix: add Android dark theme coverage (#46249) (thanks @sibbl)

---------

Co-authored-by: Ayaan Zaidi <hi@obviy.us>
2026-03-15 08:35:04 +05:30
Tak Hoffman 29fec8bb9f
fix(gateway): harden health monitor account gating (#46749)
* gateway: harden health monitor account gating

* gateway: tighten health monitor account-id guard
2026-03-14 21:58:28 -05:00
Vincent Koc 8aaafa045a
docker: add lsof to runtime image (#46636) 2026-03-14 19:40:29 -07:00
rstar327 ba6064cc22
feat(gateway): make health monitor stale threshold and max restarts configurable (openclaw#42107)
Verified:
- pnpm exec vitest --run src/config/config-misc.test.ts -t "gateway.channelHealthCheckMinutes"
- pnpm exec vitest --run src/gateway/server-channels.test.ts -t "health monitor"
- pnpm exec vitest --run src/gateway/channel-health-monitor.test.ts src/gateway/server/readiness.test.ts
- pnpm exec vitest --run extensions/feishu/src/outbound.test.ts
- pnpm exec tsc --noEmit

Co-authored-by: rstar327 <114364448+rstar327@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 21:21:56 -05:00
Tak Hoffman f00db91590
fix(plugins): prefer explicit installs over bundled duplicates (#46722)
* fix(plugins): prefer explicit installs over bundled duplicates

* test(feishu): mock structured card sends in outbound tests

* fix(plugins): align duplicate diagnostics with loader precedence
2026-03-14 21:08:32 -05:00
Radek Sienkiewicz e3b7ff2f1f
Docs: fix MDX markers blocking page refreshes (#46695)
Merged via squash.

Prepared head SHA: 56b25a9fb3
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-15 02:58:59 +01:00
songlei df3a247db2
feat(feishu): structured cards with identity header, note footer, and streaming enhancements (openclaw#29938)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: nszhsl <512639+nszhsl@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 20:31:46 -05:00
Tak Hoffman f4dbd78afd
Add Feishu reactions and card action support (#46692)
* Add Feishu reactions and card action support

* Tighten Feishu action handling
2026-03-14 20:25:02 -05:00
Hiago Silva 946c24d674
fix: validate edge tts output file is non-empty before reporting success (#43385) thanks @Huntterxx
Merged after review.\n\nSmall, scoped fix: treat 0-byte Edge TTS output as failure so provider fallback can continue.
2026-03-14 20:22:09 -05:00
Tomsun28 c57b750be4
feat(provider): support new model zai glm-5-turbo, performs better for openclaw (openclaw#46670)
Verified:
- pnpm build
- pnpm check
- pnpm test:macmini

Co-authored-by: tomsun28 <24788200+tomsun28@users.noreply.github.com>
Co-authored-by: Tak Hoffman <781889+Takhoffman@users.noreply.github.com>
2026-03-14 20:19:41 -05:00
Radek Sienkiewicz 4c6a7f84a4
docs: remove dead security README nav entry (#46675)
Merged via squash.

Prepared head SHA: 63331a54b8
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Co-authored-by: velvet-shark <126378+velvet-shark@users.noreply.github.com>
Reviewed-by: @velvet-shark
2026-03-15 01:40:00 +01:00
Tak Hoffman 774b40467b
fix(zalouser): stop inheriting dm allowlist for groups (#46663) 2026-03-14 19:10:11 -05:00