Skip to content

Architecture: remove duplicate BlueBubbles schema in core (boundary violation) #69238

@omarshahine

Description

@omarshahine

Summary

Core (src/config/zod-schema.providers-core.ts:1425-1492) defines its own BlueBubblesAccountSchemaBase / BlueBubblesAccountSchema / BlueBubblesConfigSchema that duplicates the plugin-owned schema in extensions/bluebubbles/src/config-schema.ts. Schema additions need to be made in two places to land cleanly, and adding a single optional field requires touching three coupled artifacts (plugin schema, core schema, generated bundled-channel-config-metadata.generated.ts).

This was discovered while landing #69193 (sendTimeoutMs): the PR added the field to the plugin schema only. openclaw config set channels.bluebubbles.sendTimeoutMs 45000 failed with must NOT have additional properties because:

  1. Core Zod schema (BlueBubblesAccountSchemaBase.strict()) rejected the unknown field at OpenClawSchema.safeParse.
  2. Generated Ajv metadata (src/config/bundled-channel-config-metadata.generated.ts) was stale, so the secondary JSON-Schema validation (validation.ts:932) rejected it again.

Both are downstream of the plugin-owned Zod schema and shouldn't exist as independent sources of truth.

Boundary impact

Per CLAUDE.md:

Boundary rule: core must not know extension implementation details. Extensions hook into core through manifests, registries, capabilities, and public openclaw/plugin-sdk/* contracts. If you find core production code naming a specific extension... call it out and prefer moving coverage/logic to the owning extension or a generic contract test.

The duplicate violates this rule by name (BlueBubbles* symbols in core).

Proposed direction

  • Delete BlueBubblesAccountSchemaBase / BlueBubblesAccountSchema / BlueBubblesConfigSchema from src/config/zod-schema.providers-core.ts.
  • Migrate the few core consumers (config.allowlist-requires-allowfrom.test.ts, config.schema-regressions.test.ts, etc.) to either:
    • the plugin-owned schema via openclaw/plugin-sdk/bluebubbles / the test-utils bundled-plugin-public-surface helper, or
    • generic channel-contract assertions instead of BlueBubbles-specific ones.
  • Confirm OpenClawSchema validation still flows through normalizeBundledChannelConfigsgetDirectChannelRuntimeSchema → plugin Zod schema; remove any path that double-validates against a separately-maintained core copy.
  • Keep the generated bundled-channel-config-metadata.generated.ts regen step (pnpm config:channels:gen) — it's the right pattern, just needs to be the only secondary surface.

Out of scope

  • iMessage/Matrix/Discord/etc. likely have similar duplicates — file separately if confirmed; this issue is BlueBubbles only so the change set stays reviewable.

Context

Discovered: 2026-04-19, while testing #69193.
PR #69193 follow-up commits added belt-and-suspenders fixes to the duplicate surfaces (27bdf2d, 606f5e4) so the field works today; this issue tracks removing the duplication itself.

Metadata

Metadata

Assignees

Labels

maintainerMaintainer-authored PR

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions