Releases: WonderInventions/openclaw-roam
Release list
v0.5.1
Handle signed v1 webhook.verification challenges so Roam can complete the webhook endpoint handshake.
Changes since v0.5.0
- Recognize enveloped
webhook.verificationdeliveries - Synchronously echo
data.challengebefore normal chat-event parsing - Reject invalid signatures before any challenge handling
- (#48)
Publishing to npm via OIDC trusted publishing (release workflow).
v0.5.0
Adopt Roam API 2026-07-07 so the plugin speaks the common v1 webhook envelope and structured error codes.
Changes since v0.4.3
- Pin
ROAM_API_VERSIONto2026-07-07(was2026-06-01) - Unwrap webhook envelope
{ type, eventId, timestamp, apiVersion, data }while still accepting bare baseline payloads - Parse v0/v1 API error bodies; treat
token_revoked/invalid_tokenas permanent auth failures - Ignore
chat.messageedit/delete for agent dispatch (create-path only) - (#46)
Publishing to npm via OIDC trusted publishing (release workflow).
v0.4.3
Pin the Roam API contract this plugin speaks, ahead of the server's dated API versioning.
- Sends
Roam-Version: 2026-06-01on every request andversionon the v1webhook.subscribe, so future/v1/shape changes won't reach the plugin untilROAM_API_VERSIONis bumped in lockstep with the parsing code. - No behavior change today (no-op until the server's versioning ships).
v0.4.2
Internal refactor, no behavior change beyond the version string.
version.tsnow reads the plugin version frompackage.json(single source of truth) instead of a hardcoded constant — a release only bumpspackage.json, andUser-Agent: openclaw-roam/<version>follows automatically.
v0.4.1
Outbound Roam API requests now advertise User-Agent: openclaw-roam/<version>, so the appserver can attribute traffic to this plugin and its version in logs and Datadog (@plugin.name / @plugin.version).
- New
fetchRoamApichokepoint stamps the User-Agent on every Roam API call while preserving caller headers. version.tsconstant kept in sync withpackage.jsonby a drift-guard test.- Older installs send Node's generic
nodedefault and remain unattributable by design.
Full diff: #40
v0.4.0
Breaking change defaults
v0.4.0 replaces the DM pairing flow with a simpler, harder-to-bypass model. Operators who had dmPolicy / groupPolicy unset will see behavior change — see Migration below.
Access model
- Personal Bots (PAT,
rmp-) now respond only to their owner, automatically. The plugin discovers the owner from/v1/token.infoat startup and drops every inbound wheresenderId !== ownerId, uniformly across DM and group. An adversary creating a private group and adding the bot can no longer reach it (#24). - Org Bots (API key,
rmk-) now respond to anyone in the workspace by default. The pairing flow is no longer required (#25). UseallowFrom/groupAllowFromfor opt-in sender allowlists; usedmPolicy: "allowlist"orgroupPolicy: "allowlist"for hard per-surface gates.
Both restrictive modes remain available as explicit opt-ins (dmPolicy: "pairing", groupPolicy: "allowlist").
Migration
- Personal bots: no action needed. Owner-only is the natural enforcement of the old "only you can talk to it" property and is now active automatically.
- Org bots without explicit
dmPolicy: DMs become open to any workspace member (previously: pairing required). If that's not what you want, setdmPolicy: "allowlist"(+allowFrom: [...]) ordmPolicy: "pairing". - Org bots without explicit
groupPolicy: the per-groupgroupsmap no longer acts as a hidden allowlist (it already didn't at runtime since v0.3.2; the schema default just catches up). If you need a strict per-group gate, setgroupPolicy: "allowlist".
Other
- Removed the SDK's
requireChannelOpenAllowFromguard from the Roam schema — it requiredallowFrom: ["*"]whendmPolicy: "open", which contradicts the new default. With "open" as the default the conscious choice is to restrict, not expose.
Full Changelog: v0.3.3...v0.4.0
v0.3.3
Fixes
-
Preserve microsecond timestamp on inbound messages (#22). Roam indexes messages by exact microsecond timestamp. The plugin was truncating webhook timestamps to ms and multiplying back to µs for proactive bots starting a new thread under a top-level message — losing the µs remainder and producing thread parents Roam didn't recognize.
chat.postreturned 400 ("threadTimestamp X is not an existing message"); user saw the typing indicator but no reply.RoamInboundMessagenow carries only the immutable µs identifier (timestampMicros). The few consumers that need aDate.now()-style ms value convert at the boundary; the lossy form is never stored on the message itself.
Full Changelog: v0.3.2...v0.3.3
v0.3.2
Fixes
- Honor
groupPolicy: \"open\"literally (#19). When the policy isopen, the per-groupgroupsmap no longer acts as a hidden allowlist — listed entries are optional overrides. Fixes the silent(not allowlisted)drop when the bot was added to a new group that hadn't been pre-configured.
UX
- Courtesy notice on mention in an unlisted group (#20). When
groupPolicy: \"allowlist\"is in effect and the bot is @-mentioned in a group the operator hasn't allowlisted, post a single reply explaining how to enable it (debounced per chat per process) instead of dropping silently.
Full Changelog: v0.3.1...v0.3.2
v0.3.1
Fixes
- Group replies were being silently dropped. Set
sourceReplyDeliveryMode: \"automatic\"on the dispatch so the host doesn't suppress delivery in groups (#17).
Docs
- Add
AGENTS.mddeveloper guide covering the non-obvious concerns in the codebase: PAT vs org token shapes, microsecond timestamps,chat.historyfield drift, the suppressDelivery trap, and how thetestdata/openclaw-fixtures/contract stays in sync with wonder (#18).
Full Changelog: v0.3.0...v0.3.1
v0.3.0
- Resolve bot identity from
/v1/token.infofor Organization API keys (rmk-…). Previously only Personal Access Tokens (rmp-…) populated the bot persona, so org accounts logged "Could not fetch bot identity from token.info; self-message filtering disabled" and would loop on their own replies whenrequireMention: false. - New per-group
channels.roam.accounts.<id>.groups.<chatId>.replyInThread: trueoption. When the inbound is at the top level, the bot starts a new Roam thread under that message; when the inbound is already in a thread, the bot replies in that same thread (unchanged). Default off. - Move the
chat.typingindicator pulse to after all drop gates (self-message, allowlist, sender policy, mention gate). Dropped messages no longer surface a typing indicator (privacy fix in shared channels). - Drop-reason log lines now include the account id —
roam[default]:/roam[org]:— to make multi-account debugging unambiguous.