F267: Channel-level single identity binding (mechanism layer) - #1196
Open
kaverjody wants to merge 1 commit into
Open
F267: Channel-level single identity binding (mechanism layer)#1196kaverjody wants to merge 1 commit into
kaverjody wants to merge 1 commit into
Conversation
When a cat-cafe deployment connects to external IM channels (feishu/
dingtalk/wechat/telegram groups) that contain non-roster members
(external agents, bots, or humans), every cat currently prefixes its
own roster display name (砚砚/小狸/宪宪/小捷/金哥/烁烁 + 🐱) to
outbound messages. External members cannot distinguish these names —
they only ever opted in to one identity (e.g. "咖啡猫"). The
resulting noise (60% of message length is signature), the inability
to recognize the actor, and the leakage of internal shorthand are
all collaboration blockers for cross-roster scenarios.
This PR introduces the mechanism layer (Phase 1) of a three-phase
fix: each (connector, chat) pair can declare a single outbound
display identity; OutboundDeliveryHook enforces it at the adapter
edge, so any cat's natural display name is replaced before delivery.
DMs and cat-cafe home threads are explicitly excluded from the
override so the multi-cat authoring experience is preserved inside
the home environment.
Layer B (agent prompt identity pin) and Layer C (IM Hub audit
dashboard) are scoped for follow-up PRs and tracked in F267.
Changes:
* packages/api/src/infrastructure/connectors/channel-identity.ts
New: ChannelIdentityRegistry + CHANNEL_IDENTITY_DEFAULTS, with
explicit set/unset/list/resolve and resolveForChatType honoring
DM behavior (KD-2).
* packages/api/src/infrastructure/connectors/OutboundDeliveryHook.ts
New: channelIdentityRegistry option, resolveBindingIdentity pure
resolver, per-binding identity collapse in executeDelivery, and
an F267 audit log line when override fires.
* packages/api/test/channel-identity-override.test.js
New: 9 unit tests covering the registry contract.
* packages/api/test/outbound-identity-override.test.js
New: 5 unit tests covering the pure resolver, including the
"no registry" and "empty natural name" edges.
* docs/features/F267-channel-single-identity.md
New: full spec with AC (Phase 1/2/3), KD log, dependencies, risk
matrix, behavioral evidence cases.
* docs/references/im-channel-public-contract.md
New: public contract for external collaborators — which
cat-cafe internal shorthands they can safely ignore, which
formats are guaranteed, and which patterns are noise to filter.
* docs/README.md
Reference index updated to point at the new IM Channel Public
Contract doc and at the F267 spec.
Out of scope (intentional, for follow-up PRs):
- SystemPromptBuilder identity pin injection (Phase 2)
- IM Hub audit dashboard (Phase 3)
- FeishuAdapter in-group gate, fingerprint loopback guard, full
OutboundSanitizationLayer (P1 items in the issue body)
Refs: issue zts212653#1195 (Channel-level single identity binding for IM
connectors).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
This PR introduces the mechanism layer (Phase 1) of F267: per-
(connector, chat)channel identity override, enforced at theOutboundDeliveryHookadapter edge.For every cat that posts to an external IM channel (feishu / dingtalk / wechat / telegram groups) which contains non-roster members, the natural display name (砚砚 / 小狸 / 宪宪 / 小捷 / 金哥 / 烁烁) is replaced at the adapter edge with the channel-configured identity. Default for feishu groups is
咖啡猫 🐱; DMs explicitly opt out (KD-2) so the home-environment multi-cat authoring experience is preserved.Why
External collaborators only ever opted in to a single identity. They cannot tell 砚砚 from 宪宪, and 60% of every message in a busy group is signature noise. This blocks real collaboration with openclaw / hermes / humans who do not share the cat-cafe context. Layer B (prompt pin) and Layer C (audit dashboard) are scoped for follow-up PRs — this PR is the harness-level floor that makes Layer A work without trusting the model.
Files
7 files changed. 5 new, 2 modified.
Acceptance Criteria covered
OutboundDeliveryHook.executeDelivery增加channelIdentityOverride解析 →resolveBindingIdentity纯函数解析displayName='咖啡猫'→ 出站 envelope 强制为【咖啡猫🐱】,即使 cat agent 输出【砚砚🐱】overridden: falsedisplayName='咖啡猫';飞书 DM 不走 overridecatDisplayName推导前多一步 resolve)channel-identity-override.test.js9 cases +outbound-identity-override.test.js5 casesTest plan
cd packages/api && pnpm install && pnpm build— 编译通过(channel-identity.ts+OutboundDeliveryHook.ts强类型契约)node --test packages/api/test/channel-identity-override.test.js— 9 cases 全绿node --test packages/api/test/outbound-identity-override.test.js— 5 cases 全绿【咖啡猫🐱】前缀,不看到【砚砚🐱】/【小狸🐱】等Out of scope (follow-up PRs)
SystemPromptBuilder注入ChannelIdentityPin到 cat prompt(Layer B 治本)OutboundSanitizationLayer(issue Channel-level single identity binding for IM connectors (feishu/dingtalk/wechat/telegram groups) #1195 内 Fix 1/3/4)Key Decisions
exposeInternalNames: false默认Risk
Closes #1195