Skip to content

Spec: Bot-scoped external user roles and automatic conversation pairing #1371

Closed
0 of 1 issue completed

Description

@DoodleBears

Problem Statement

An administrator wants to share a Bot in company IM conversations while controlling which people can ask it to do work. A new member of a restricted group should not be able to start a model turn simply by mentioning the Bot. Approved people should receive behavior appropriate to their assigned role, and ordinary conversational access should not require granting tool-approval powers.

Today, binding an app enables its qualified default traffic, subject to conversation policy. Existing Lark /pair requests grant reviewed operational capabilities, require at least one such capability, and do not define ordinary conversation eligibility. There is no Bot-scoped external-user role directory or automatic sender-pairing flow for an unknown user's DM or group mention.

The motivating use case is asking a Bot about company email through its existing Shell and Himalaya CLI. This spec supplies generic conversation admission and role context; mailbox credentials and email execution remain independent.

Solution

Add Bot-scoped external-user roles and reviewed conversation pairing, configured by the Human in the Bot DM Channel sidebar beside external identities and approvals.

A role has a name, natural-language behavioral permissions, and an explicitly selected set of structured management capabilities. For example, a normal role can describe whether the Bot should query email or modify code while having no approval capabilities. These natural-language permissions are prompt behavior policies, not enforced resource ACLs for arbitrary Shell commands. Management actions supported by the Host continue to require deterministic authorization.

The Human can require pairing for a Bot's external conversations and explicitly make particular groups open to visitors. For a reachable, allowed restricted conversation, an unknown person's DM or mention creates or reuses a pending pairing request and receives a fixed response. It does not invoke the LLM or schedule the blocked request. The Human reviews the request and selects one role. Approval persists the pairing and sends a fixed success notice asking the person to submit a new message; it never replays the old message.

Pairing is scoped to one Bot, one current app/account Binding, and the authenticated provider user identity. Approval can be reused across that Bot/app's otherwise allowed restricted conversations. It does not carry to another Bot, another app, another platform, or a replacement Binding. Platform reach, conversation blocks, collection rules, mentions, and Wake Policy remain independent controls.

On an admitted request, the Bot receives trusted sender and message/conversation references, separate from message content. The Host does not automatically inject that person's role, permission text, or a role-policy snapshot into every Inbox turn or system prompt. A read-only single-person permission-query Tool resolves a trusted actor reference in the Bot's authorized scope and returns the current pairing status, role, natural-language permissions, structured management capabilities, policy revision, and query time. Ordinary conversation need not call it; the Bot is guided to query the requester before handling a new permission-sensitive request.

This lookup complements three small, read-only directory views: approved paired people and roles, known external conversations, and observed paired participants of a selected conversation. The last view is an observation history with coverage information, not complete or current membership. Each permission lookup reads current canonical state; historical Tool Results are dated execution evidence and do not update themselves. Tool usage and natural-language permissions remain behavioral policy; admission and supported management decisions are still independently enforced by the Host.

First runnable tracer bullet: on one real Lark app, create an ordinary role with no management capabilities; an unknown user mentions the Bot in a restricted group; review the resulting request in the real sidebar; approve the role; observe a fixed re-ask notice; send a new mention and receive a real model reply in the original group with trusted sender provenance; demonstrate an on-demand current-permission lookup for a role-governed request; query the scoped directory; revoke pairing and verify the next mention does not start the model. Obtain Human feedback on this slice before expanding provider coverage or additional management controls.

User Stories

  1. As a Bot administrator, I want to define roles for my Bot, so that I can describe how it should respond to different external people.

  2. As a Bot administrator, I want each role to contain natural-language permissions, so that I can express policies such as email-query access without building a dedicated integration for every resource.

  3. As a Bot administrator, I want structured management capabilities to be selected separately from that text, so that a conversational role cannot accidentally acquire approval authority.

  4. As a Bot administrator, I want an ordinary role to have an empty management-capability set, so that people can talk to the Bot without becoming approvers.

  5. As a Bot administrator, I want operational role and pairing settings in the Bot DM sidebar, so that local authorization is managed beside the app bindings rather than in a shareable Profile.

  6. As a Bot administrator, I want to enable restricted sender admission independently of conversation reception, so that app binding and group collection do not silently decide who may make requests.

  7. As an unknown external user, I want my first DM or mention in an allowed restricted conversation to start a pairing request, so that I can request access without learning a separate setup procedure.

  8. As an external user, I want an explicit /pair entry point to remain available, so that I can deliberately request access.

  9. As a Bot administrator, I want pending requests to use verified sender and app identities, so that a nickname, quoted message, or claimed role cannot determine access.

  10. As a Bot administrator, I want unknown users' blocked requests to receive deterministic handling without model calls, so that unsolicited messages cannot spend model tokens by triggering work.

  11. As a Bot administrator, I want duplicate and repeated requests to be deduplicated, bounded, rate limited, and expirable, so that pending requests and fixed notices cannot grow without limit.

  12. As a Bot administrator, I want to select exactly one role when approving a pairing request, so that the approved person's effective policy is clear.

  13. As an approved external user, I want a fixed success notice asking me to send my question again, so that I know when access starts and no stale request runs unexpectedly.

  14. As a Bot administrator, I want notification failure to leave the recorded approval intact without replaying a request, so that transport retries do not change authorization or launch work.

  15. As an approved external user, I want one approval to work across otherwise allowed restricted conversations of the same Bot/app, so that I do not need to pair separately in every group.

  16. As a Bot administrator, I want approvals isolated across Bots, apps, and platforms, so that membership in one scope does not grant access elsewhere.

  17. As a Bot administrator, I want replacing or rebinding an app to avoid inheriting old user authority, so that an obsolete binding cannot authorize the new receiver.

  18. As a Bot administrator, I want to revoke a pairing or change its role, so that future requests use current access rather than an old prompt or cached assignment.

  19. As a Bot administrator, I want blocked or unavailable conversations to remain blocked even for paired people and open groups, so that sender eligibility does not override platform or conversation restrictions.

  20. As a Bot administrator, I want to mark a particular group explicitly open, so that visitors can ask questions there without individual pairing.

  21. As a Bot administrator, I want visitors in open groups to have no management authority, so that open conversation access cannot decide approvals.

  22. As a Bot administrator, I want mention and Wake Policy preferences to remain effective after sender admission, so that authorization does not force every eligible message to wake the Bot.

  23. As a Bot administrator, I want ordinary unpaired group messages to remain available only as separately authorized passive context, so that collection can be useful without treating every speaker as a requester.

  24. As a Bot administrator, I want those passive messages excluded from request-trigger counts and batch wake thresholds, so that unpaired participants cannot indirectly schedule a turn by filling a batch.

  25. As an approved external user, I want the Bot to resolve my current permissions on demand using my trusted message identity, so that it can follow my role's behavior policy without injecting permissions on every message.

  26. As a Bot administrator, I want each author in a multi-author batch to retain separate trusted identity and queryable provenance, so that a permission lookup for one person cannot transfer or combine another person's management powers.

  27. As a Bot, I want to query my approved paired people and their roles, so that I can reason about the identities already authorized in my scope.

  28. As a Bot, I want to query my known external conversations and their states, so that I can distinguish configured or observed conversations without inventing platform reach.

  29. As a Bot, I want to query observed paired participants of a conversation with timestamps and coverage information, so that I can use available context without pretending to know all current members.

  30. As a Bot administrator, I want those directory queries scoped and read-only, so that the model cannot discover another Bot's directory or grant itself access.

  31. As a Bot administrator, I want supported approval actions checked against the actual actor's current structured capabilities, so that visible buttons and natural-language claims do not authorize a management decision.

  32. As a Bot administrator, I want pending requests, roles, and revocations to survive Host restarts with current-state checks, so that recovery does not reopen access or execute old messages.

  33. As a Bot administrator, I want existing explicit management grants and conversation policies preserved during rollout, so that the new feature does not silently replace or broaden existing authorization.

  34. As an external group participant, I want admitted replies to follow the Bot's existing checked reply route, so that questions are answered in the original conversation when that route remains valid.

  35. As a Bot administrator, I want clear notice that group replies are visible to group members and prompt permissions are behavioral policies, so that I can choose appropriate groups and execution credentials.

  36. As a Bot administrator, I want a new permission lookup after a role update to return the new canonical policy and its revision, so that old conversation history is not mistaken for current authority.

  37. As a Bot administrator, I want permission-query failures or ambiguous actor references to remain unresolved rather than be guessed from names or prior results, so that the Bot can defer a policy-governed request until it has valid information.

Implementation Decisions

  • Owner and authority. This is application-defined BotHarness Messaging behavior. Extend the existing Messaging owner and Operational Database authority for roles, role assignment, pending pairing, and sender policy. Use the existing qualified Provider's exclusive Consumer/fanout, canonical Source Events, Inbox Admission, and checked reply/outbox lifecycle. Do not introduce another platform listener, a second pairing database, or an email-specific module.
  • Separate axes. Sender admission, platform reach, Binding readiness, conversation reception/block state, collection, mention rules, and Wake Policy remain distinct. Restricted sender policy adds a gate to the existing one-step app-binding behavior; it does not reinstate per-conversation setup for qualified default traffic. A paired sender or explicitly open group cannot bypass an earlier scope restriction or durable block.
  • Role model. A role belongs to one Bot and contains a stable reference, display name, behavioral permission text, explicitly selected structured management capabilities, and a revision. A pairing has one effective role per Bot/app identity in this version. There are no role hierarchies, combined roles, or per-person permission overrides. Role assignment and changes are Human-reviewed operations; no model-directed directory mutation is exposed.
  • Identity key. Bind authorization to the Bot, current Binding/account fingerprint, and provider-authenticated sender identity in its required namespace. Display names, user-provided IDs, pairing codes, and local UUIDs are not proof of identity. Cross-conversation reuse is allowed only where the qualified Provider establishes the same authenticated actor namespace. No cross-platform or cross-app identity matching is inferred.
  • Deterministic request gate. Handle intentional DM, mention, and explicit pairing controls before a restricted request can become a Bot Inbox Admission, a wake contribution, or model work. Cover default traffic, explicit conversation ingest/Bridge paths, followed-thread reception, and shared-source paths as applicable; gating only the default-traffic branch is insufficient. Shared canonical sources do not transfer one Bot's pairing to another Bot.
  • Pending state. Automatic pairing means automatically creating a request, not approving it. Store bounded identity, scope, lifecycle, and verified reply-reference metadata needed for review and notification. Do not retain the blocked request body as deferred executable input or copy it into model context, Memory, or trigger batches. Retain existing deduplication, expiry, stale-revision checks, and bounded control-intake behavior; make additional rate and capacity bounds observable through stable refusal reasons.
  • Approval and notification. The authenticated Web Human selects the role and approves the current request through the existing Host-to-Client service seam. Empty management capabilities are valid for an ordinary role. Approval commits before a deterministic success notification through a currently checked original reply route; do not assume that a group user can be privately messaged. A failed notice does not undo pairing, retry model execution, or backfill the old request. The next new message is checked against current state.
  • Open conversations and background context. An explicitly open group admits visitors with a non-management behavioral context, while existing scope and wake checks still apply. Ordinary group collection does not generate bulk pairing requests. Unpaired text may be passive context only inside the separately authorized collection/read scope and must not contribute to request or batch wake thresholds. This does not guarantee that such context cannot influence a later authorized model turn or consume tokens when read.
  • Trusted identity and on-demand permissions. Attach only the small trusted sender/actor reference, Bot/app scope, and source/message/conversation provenance needed to attribute each request. Do not automatically attach role/permission snapshots per message or force a permission lookup on every Inbox turn. Provide an application-defined, read-only single-person Tool through the existing Messaging Service and model-facing Consumer. Resolve the subject reference under the calling Bot's current authority; do not trust a caller-supplied Bot identity, display name, quoted identity, or claimed role. Return current pairing status (including no effective pairing), effective role where applicable, behavioral permission text, structured capabilities, policy revision, and query time. A visitor or revoked/unpaired subject gains no capability from being queryable. Wrong-scope, ambiguous, missing, and unavailable references return bounded explicit results/errors without substituting another identity or old permissions.
  • Query freshness and use. Read current canonical pairing/role/Binding state on each lookup; do not reuse a previous policy snapshot as a current Tool response. Stable behavioral guidance asks the Bot to query the actual requester for a new permission-sensitive request and defer the governed operation if the lookup is unavailable or unresolved. Ordinary conversation need not query. Querying another person is informational and never authorizes acting as that person. Return compact results instead of injecting the directory or permission text for every author. A role update is observable on the next lookup, not automatically pushed into historical Tool Results or guaranteed to stop an in-flight arbitrary Shell command. Tool-call compliance remains prompt behavior policy; hard admission/action checks do not depend on a prior lookup.
  • Multi-author attribution. Preserve distinct trusted identity per event and resolve permissions for the actual requester as needed; do not use the last sender, the most privileged sender, or a union of queried permissions as authority for the whole batch. Background messages, quoted administrators, cron work, and later Assignments do not acquire an external person's management authority by proximity.
  • Structured action checks. Keep conversational eligibility separate from management capabilities. For supported management actions, validate the real actor, Bot/app scope, current pairing and role state, request destination, and action-specific lifetime immediately before accepting the decision. Existing capability names such as approve, reject, answer, and save-rules are BotHarness-defined; native DSH user-approval and user-questions are separate Services. Do not present all stored capability names as already implemented IM actions. A role's ability to approve also does not create a standing rule that automatically approves its future commands. Existing Tool Approval Rule execution roles are distinct from these external-user roles.
  • Read-only directory. Expose bounded, pageable queries for effective paired people and roles; the Bot's known/configured conversations and states; and observed paired participants of a selected conversation. Derive observations from trusted sender/conversation evidence visible to that Bot, intersected with current effective pairing. Include observation times and explicit incomplete/retention coverage. Do not infer silent members, current membership, departure, or permission to reach a conversation from this view. Scope shared-source visibility through the receiving Bot's actual authority rather than a source's original owning Bot alone.
  • Lifecycle and compatibility. Re-check current authority after revocation, role changes, Binding disable/replacement, restart, and delayed delivery. Configure restricted sender admission explicitly; do not silently convert all existing conversation access into a new restricted policy or treat old management pairing as conversational approval. Preserve current explicit management grants without granting additional powers, and preserve existing conversation blocks, collection settings, and app-binding defaults. Migration must not turn missing policy or identity evidence into a new open-group exception.
  • Client surface and diagnostics. Reuse the Bot DM sidebar, existing pairing review and authenticated API Gateway/Client transport. Show scope, selected role, empty-capability ordinary access, pending/approved/revoked state, and prompt-policy limitations clearly. Use native in-harness UI tokens and primitives. Record bounded, stable developer lifecycle evidence for request, review, refusal, notification, and revocation without secrets, blocked message bodies, or unrestricted directory dumps.
  • Delivery order. Implement and validate the smallest Lark intake → durable request → real sidebar review → fixed notice → fresh-message model reply with trusted identity and on-demand permission lookup → directory → revocation path first. Broader provider coverage and management interactions follow Human feedback and the existing sibling issues. Record durable architecture choices and integrate accepted runtime boundaries into the living architecture during implementation.

Testing Decisions

  • Prefer the highest existing production seam: qualified Messaging intake into the public core/Bridge API, with the real Host authority and existing Client review transport. Use a recording Bot Agent Adapter to observe Orchestrator starts and a qualified fake Provider to observe checked notifications and replies. Add focused Client interaction coverage for role selection and an ordinary role with no management capabilities. Test observable state and side effects rather than private functions or schema layout.
  • Reuse prior art from the Bot pairing, Messaging default-traffic, Consumer fanout, conversation-ingest, Lark approval, Tool Approval Rule, and pairing-settings suites. Existing default-traffic tests already exercise a qualified IM Service with recorded Bot execution; extend that seam rather than creating a separate authorization simulator.
  • Prove that a first and duplicate unknown restricted DM/mention produce bounded pending state and deterministic output with zero model starts, zero request Inbox Admissions, and zero wake/Task contributions. Include expiry, capacity/rate refusal, blocked conversation, unavailable Binding, and explicit /pair. Ordinary collected group text must not create pairing requests.
  • Prove that real review accepts a selected ordinary role with no management capabilities, persists across restart, and sends a fixed re-ask notice. Approval and notification retries never execute or backfill the blocked message; a failed notice leaves a valid approval. A fresh message carries trusted requester provenance and uses the checked original reply path; a role-governed demonstration obtains current permissions through the Tool rather than automatic role injection.
  • At the public Messaging/model-facing Tool seam, prove compact trusted identity is available without automatic role/permission injection, ordinary conversation does not force a permission lookup, and a role-governed request can query its real requester. Edit/reassign the role between two lookups in one Session and verify the second result reflects current state with a new revision/time while the first result remains historical. Test revoked/unpaired status, visitor no-capability behavior, wrong Bot/app references, ambiguous identity, unavailable queries, and refusal to impersonate a queried subject. Observing a Tool call is not proof of enforced arbitrary resource ACLs.
  • Exercise all intake paths capable of scheduling this Bot, including explicit ingest and shared-source delivery. Unpaired passive text can remain authorized background context but cannot trigger a count/time batch; paired authors in the same batch keep separate role provenance.
  • Prove same Bot/app cross-conversation reuse and isolation across Bots, apps, provider identity namespaces, and replacement Bindings. Test revocation, stale review revisions, role changes, delayed controls, restart recovery, and current-state checks rather than relying on cached prompt data.
  • Prove open-group visitors can make ordinary requests under the existing mention/wake policy while lacking management authority. Check that durable blocks and platform/account restrictions win. For already supported management controls, a person without the required structured capability cannot complete the actual native request, regardless of button visibility or claimed role text.
  • Prove all three directory views are read-only, bounded, and scoped. An approved person observed in one group appears there; a paired but never-observed person is not invented as a member. Revoked or wrong-scope people are not returned as effective paired participants. Expose incomplete or retention-limited coverage, including shared-source and purge cases.
  • Verify migration preserves existing explicit capabilities and conversation policy without silently granting conversational approval, opening restricted groups, or resetting app defaults. Do not use a legacy management pairing as the sole proof of new conversation eligibility.
  • Provide a runnable isolated Host with the real Bot sidebar and a test Lark app for the first tracer. Human acceptance follows the Solution flow, includes a real model reply and evidence that unknown/revoked mentions make no model call, and uses a separate test receiver or an explicitly coordinated exclusive window. Do not take over a production receiver to prove the slice. Capture UI evidence under the repository's normal in-harness verification workflow; automated tests alone do not complete this cross-layer tracer.

Out of Scope

  • Email Providers, Plugins, MCP servers, wrappers, mailbox UI, Fastmail/Himalaya credentials, or changes to how the Bot invokes Shell. Local and production mailbox acceptance for main@vereach.ai is a separate task. Email sending is not added here.
  • Hard per-external-user email, repository, arbitrary Shell, or credential isolation. Natural-language role text is an accepted behavioral policy and does not change the execution identity's resource permissions.
  • Complete/current platform membership synchronization, dynamic audience authorization, per-reply disclosure confirmation, or hiding a group reply from selected members. Group replies remain visible to the group's audience.
  • Automatic cross-Bot/app/platform identity merging, role hierarchy, multiple roles per person, per-person overrides, or a general policy language.
  • New Provider capabilities for arbitrary group search, message search, or proactive posting. These remain independent of who may ask the Bot questions.
  • Slack, Discord, WeChat, or QQ runtime expansion before feedback on the first Lark slice. No claim is made that QQ is an implemented Provider today.
  • Reimplementing the existing IM management roadmap, including native questions, save-rules, management-group controls, or each provider's approval cards. This spec supplies the role/admission model and integrates current supported checks; delivery of additional actions remains with their existing issues.

Further Notes

Activity

  1. added
    ready-for-agentFully specified, ready for an AFK agent
    area:fullstackEnd-to-end Host and Client implementation
    feature:messagingMessaging module and external providers
    scope:specNormative specification for follow-on slices
    on Oct 10, 2026
  2. DoodleBears commented on Oct 10, 2026

    @DoodleBears
    ContributorAuthor

    Human-confirmed design update — on-demand permission queries

    On 2026-10-11 the Human accepted trusted identity per message + on-demand current-permission queries, replacing automatic role/permission injection on every Inbox turn or system prompt, and explicitly requested the specification and issues be updated.

    Updated this spec, Hub #1372 and implementation tickets #1373–#1376 in place. #1373 supplies the minimal single-person Tool; #1374 still supplies the three directories and complete first-flow Human acceptance. #1375 verifies role changes via fresh lookups and independent management checks; #1376 preserves visitor and passive-author provenance. Native dependencies, labels, task claims and Project states are retained.

    The new contract makes freshness observable at query time with canonical state, policy revision and query time. Historical Tool Results remain historical. Ordinary conversation does not force a lookup, and natural-language policy is still behavioral; deterministic sender admission and supported management authorization remain Host checks independent of model Tool usage.

    No implementation takeover, runtime change, new ticket, PR modification, merge, deployment or provider expansion is included in this specification update. Existing automatic-injection QA evidence is preserved but does not itself complete the revised Tool contract.

  3. DoodleBears commented on Oct 11, 2026

    @DoodleBears
    ContributorAuthor

    The confirmed first-version specification is delivered: #1373–#1376 are closed, their four PRs #1377/#1379/#1387/#1388 merged into main after Human acceptance and refreshed exact-head full CI. Latest UI and complete first-flow feedback are accepted; native dependencies were fulfilled. See Hub #1372 current delivery for SHAs, CI and evidence. Hub #1372 remains open for separate unimplemented design follow-ups #1392/#1404; these do not change this spec approved first-version scope. No release/deployment/receiver restart. Task codex/local/01a12734-8226-7ae3-8d1b-db08bde64d76; completed for approved implementation/merge.

  4. moved this from Todo to Done in Roadmapon Oct 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area:fullstackEnd-to-end Host and Client implementationfeature:messagingMessaging module and external providersready-for-agentFully specified, ready for an AFK agentscope:specNormative specification for follow-on slices

    Type

    No type

    Projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions