chaitin / chaitin/MonkeyCode

设计并实现 MonkeyCode 端点桥接通信协议

Open
#891 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

ready-for-agent
Dominant language
TypeScript
Stars
4.7k
Forks
719
Avg merge
4h 30m
Merged PRs (30d)
83

Description

Problem Statement

MonkeyCode 用户会同时在桌面端和移动端使用同一个账号,但现有通信能力围绕具体任务、终端或文件场景分别建设,客户端之间缺少一个稳定、通用且与 Agent 业务模型解耦的发现与通信通道。手机端因此无法可靠发现电脑端,也无法通过统一协议接续电脑端 Agent 正在处理的任务;新的跨端能力还会反复处理身份、鉴权、在线状态、消息关联和多副本路由等基础问题。

用户需要的是同一账号下原生端点之间可直接发现、双向通信的基础设施。桥接服务应只承担用户鉴权、端点目录、在线状态和消息路由,不理解任务或文件等业务语义,也不能把团队、项目或管理员权限隐式扩大为对用户本地端点的控制权。

Solution

为 MonkeyCode 原生桌面端和移动端提供一套主版本为 1 的端点桥接协议。每个应用安装实例是一个端点,并与一个 Agent 一一对应;首次安装生成并安全保存随机 UUID 作为机器标识,服务端使用当前登录用户与机器标识的组合识别和寻址端点。

客户端复用现有登录 Cookie,通过 /api/v1/endpoints/connect 建立 WSS 长连接,完成 hello / welcome 协商后接收同一用户发现域的完整端点目录。端点之间使用 JSON 文本帧发送单播 eventrequestresponse,桥接服务注入可信来源并完成同实例或跨实例路由。请求状态、响应关联、超时与业务幂等由客户端和 Agent 维护;桥接服务不保存离线消息、不自动重试、不发送成功送达确认,也不承诺 Agent 已成功执行。

端点资料和撤销状态持久化到 PostgreSQL,在线位置和 60 秒租约存放在 Redis,多副本之间通过 Pub/Sub 转发。文件始终保留在源端点本地,其他端点需要查看时通过 Agent 自定义消息传输;核心协议只限制单文件最大 5 MiB 和单帧最大 256 KiB,不定义文件读取方法、分块或编码。

User Stories

  1. 作为 MonkeyCode 用户,我希望同一账号登录的桌面端和移动端能够互相发现,以便从任一端继续使用自己的 Agent。
  2. 作为 MonkeyCode 用户,我希望新端点登录后无需与已有端点配对,以便快速开始跨端协作。
  3. 作为 MonkeyCode 用户,我希望团队成员、项目协作者和管理员不能自动发现我的端点,以便本地运行环境不会因业务权限而暴露。
  4. 作为首次安装客户端的用户,我希望应用自动生成稳定的随机机器标识,以便重启应用后仍被识别为同一端点。
  5. 作为切换账号的用户,我希望同一安装实例继续使用原机器标识,以便端点身份由用户与安装实例共同确定。
  6. 作为重装客户端的用户,我希望新安装生成新的机器标识,以便它被明确视为新端点。
  7. 作为注重隐私的用户,我希望端点身份不依赖 MAC 地址、硬盘序列号或硬件指纹,以便避免额外权限、隐私和克隆风险。
  8. 作为客户端,我希望复用当前登录 Cookie 建立桥接连接,以便不再维护第二套端点凭证和登录流程。
  9. 作为客户端,我希望在 WebSocket 地址或消息中无需声明用户标识,以便服务端只信任已鉴权会话。
  10. 作为客户端,我希望连接时上报设备名称、平台、系统版本、架构和客户端版本,以便其他端点能够辨认我并判断兼容性。
  11. 作为用户,我希望可以为端点设置别名,以便用“办公电脑”等熟悉名称识别设备。
  12. 作为用户,我希望别名不被后续自动上报的系统设备名覆盖,以便自定义名称保持稳定。
  13. 作为用户,我希望查看当前账号的全部端点以及在线、离线和撤销状态,以便管理自己的端点目录。
  14. 作为在线客户端,我希望在连接就绪后收到完整端点目录,以便立刻建立可用的发现视图。
  15. 作为在线客户端,我希望端点上线、离线、改名、撤销或恢复后收到新的完整目录,以便展示当前状态。
  16. 作为客户端开发者,我希望每次目录更新都是全量快照,以便客户端整体替换数组而无需维护 revision 和增量合并状态。
  17. 作为在线客户端,我希望目录包含当前端点自身和所有未撤销的离线端点,以便明确自身身份并仍可展示曾连接的端点。
  18. 作为 Agent,我希望向指定目标端点发送无需响应的事件消息,以便同步通知或状态变化。
  19. 作为 Agent,我希望向指定目标端点发送请求并接收关联响应,以便完成任务接续等由 Agent 定义的交互。
  20. 作为 Agent 开发者,我希望自行定义方法名和对象载荷,以便桥接协议不耦合任务、会话、工具或能力模型。
  21. 作为发送端客户端,我希望为每条业务消息生成 UUIDv4 消息标识,以便进行请求关联、观测和可选的业务去重。
  22. 作为接收端 Agent,我希望响应使用新的消息标识并引用原请求,以便发送端准确匹配 pending 请求。
  23. 作为发送端客户端,我希望服务端为转发消息注入可信来源和路由时间,以便不信任对端伪造的身份信息。
  24. 作为发送端客户端,我希望只有来源、目标、响应类型和引用关系都匹配时才完成 pending 请求,以便阻止错误或伪造响应串线。
  25. 作为发送端客户端,我希望默认等待响应 30 秒且允许按方法覆盖,以便在通用默认值和具体业务时延之间取得平衡。
  26. 作为发送端客户端,我希望请求超时或连接中断时得到“结果未知”,以便不会错误判断目标 Agent 未执行操作。
  27. 作为发送端客户端,我希望迟到、重复或来源不匹配的响应被忽略,以便已经结束的请求状态不会被重新激活。
  28. 作为 Agent 开发者,我希望桥接服务不维护业务请求状态,以便业务生命周期和语义始终由客户端与 Agent 控制。
  29. 作为发送端 Agent,我希望可在路由前确定的失败立即返回协议错误,以便区分目标离线、目标繁忙、限流和消息格式错误。
  30. 作为安全敏感的用户,我希望不存在、属于其他用户或已撤销的目标统一表现为不可用,以便机器标识不能用于探测其他用户端点。
  31. 作为发送端 Agent,我希望桥接服务不发送成功送达确认,以便网络写入不会被误解为 Agent 已接收或已成功执行。
  32. 作为发送端 Agent,我希望桥接服务和通用客户端库都不自动重试业务消息,以便非幂等操作不会被重复执行。
  33. 作为实现幂等方法的 Agent,我希望能够自行决定复用原消息标识进行重试和去重,以便在明确业务语义后提高可靠性。
  34. 作为接收端 Agent,我希望同一来源到同一目标的消息在双方连接连续期间保持 FIFO,以便处理依赖发送顺序的消息流。
  35. 作为 Agent 开发者,我希望协议不承诺跨发送方、跨重连或请求响应之间的全局顺序,以便需要更强顺序时可在载荷中自定义序号。
  36. 作为移动端用户,我希望查看电脑端本地文件时文件不必先上传 OSS,以便文件继续保留在源端点。
  37. 作为 Agent 开发者,我希望自行定义文件传输方法、分块、编码、校验、访问控制和错误结构,以便核心协议保持通用。
  38. 作为平台运营者,我希望单个文件暂时限制为 5 MiB、每个 JSON 帧限制为 256 KiB,以便控制首版资源消耗。
  39. 作为客户端开发者,我希望协议只使用 UTF-8 JSON 文本帧并禁用二进制帧和消息压缩,以便各原生平台实现保持一致。
  40. 作为客户端开发者,我希望通过整数主版本列表协商共同支持的最高版本,以便兼容升级和明确拒绝不兼容客户端。
  41. 作为客户端,我希望服务端使用 WebSocket 原生 Ping/Pong 检测存活,以便 Electron 和 React Native 的底层实现可以自动处理心跳。
  42. 作为已退出登录的用户,我希望桥接连接在一个心跳周期内被关闭,以便失效会话不能持续通信。
  43. 作为网络不稳定的移动端用户,我希望可恢复断线使用带抖动的指数退避重连,以便降低重连压力并自动恢复在线状态。
  44. 作为发送请求的客户端,我希望断线重连后不自动重发未完成请求,以便避免结果未知的操作被重复执行。
  45. 作为使用同一机器标识的新连接,我希望它原子替换旧连接,以便同一个端点不会同时由两个 Agent 实例执行消息。
  46. 作为被新连接替换的客户端,我希望停止自动重连,以便两个复制了同一机器标识的客户端不会形成替换风暴。
  47. 作为用户,我希望能够撤销某个端点并立即断开其连接,以便暂时禁止它参与发现和通信。
  48. 作为持有有效登录会话的用户,我希望能够显式恢复已撤销端点,以便重新启用误撤销或重新使用的端点。
  49. 作为用户,我希望撤销记录被保留且端点不能自动重新登记,以便管理状态不会因客户端重连而失效。
  50. 作为用户,我希望系统明确提示撤销不是失窃设备的完整安全处置,以便必要时同时使该设备的登录会话失效。
  51. 作为端点较多的用户,我希望默认最多保留 20 个未撤销端点并由私有化配置调整,以便资源可控且不自动淘汰已有端点。
  52. 作为多副本部署的用户,我希望两个端点连接到不同桥接实例时仍能发现并通信,以便负载均衡不会破坏跨端体验。
  53. 作为平台运营者,我希望 Redis 不可用时拒绝新连接或明确返回服务不可用,以便不会产生局部在线、全局不可达的不一致状态。
  54. 作为平台运营者,我希望目标发送队列有消息数和字节数上限,以便慢端点不会拖垮整个桥接实例。
  55. 作为发送端 Agent,我希望目标队列已满时收到目标繁忙错误,以便消息不会被静默丢弃。
  56. 作为平台运营者,我希望按用户和发送端点同时限制消息数与载荷字节数,以便单一来源不能耗尽共享资源。
  57. 作为安全负责人,我希望带非空来源头的连接必须匹配白名单,以便恶意网页不能借用登录 Cookie 建立跨站 WebSocket。
  58. 作为原生客户端,我希望可以不发送来源头但仍使用 Cookie 鉴权,以便适配原生 WebSocket 实现。
  59. 作为隐私负责人,我希望日志、指标、错误和审计永不记录业务载荷原文,以便源码、终端输出和凭据不会被持久化暴露。
  60. 作为平台运营者,我希望端点登记、撤销、恢复、连接替换、会话失效和鉴权失败进入安全审计,以便可以追踪管理与安全事件。
  61. 作为现有 MonkeyCode 用户,我希望新的桥接协议与现有任务流、任务控制和终端 WebSocket 并存,以便上线过程不破坏已有能力。
  62. 作为客户端开发者,我希望关闭码能够区分正常关闭、协议错误、过载、连接替换、端点撤销和会话失效,以便采取正确的停止或重连策略。
  63. 作为平台运营者,我希望桥接实例优雅停机时通知客户端服务重启并清理自身租约,以便滚动发布期间端点能够平滑迁移。

Implementation Decisions

  • 新增独立的端点桥接领域模块,包含端点目录、连接管理、消息信封校验、在线路由、多副本协调和 HTTP/WebSocket handler;不改造现有任务、控制和终端 WebSocket。
  • 一个端点与一个 Agent 一一对应,任务和能力是 Agent 自己管理的资源,桥接层不提供端点内的二级 Agent 路由。
  • 端点主键语义为当前用户标识与机器标识的组合。机器标识是客户端首次安装生成并安全保存的随机 UUID,不作为鉴权凭证。
  • 发现域严格限定为同一用户。团队、项目和管理员角色不参与端点授权,所有读取、管理和路由操作都从已鉴权会话推导用户范围。
  • 端点持久化资料包括机器标识、系统设备名、平台、系统版本、架构、客户端版本、用户别名、管理状态、最后在线时间和创建更新时间。展示名称由别名优先、系统设备名兜底。
  • 持久化管理状态只有启用和已撤销。首版不彻底删除端点记录;WebSocket 目录只包含未撤销端点,HTTP 管理列表包含已撤销端点。
  • 新增端点管理接口:查询全部端点、查询单一端点、修改别名、撤销和恢复;接口统一位于 /api/v1/endpoints 资源下,不挂在 /users 路径下。
  • 新增 WebSocket Upgrade 端点 /api/v1/endpoints/connect,复用现有登录 Cookie。生产强制 WSS,开发环境仅允许本机地址使用明文 WS。
  • HTTP 和 WebSocket 对不存在、属于其他用户或不可见的机器标识统一按资源不存在或 target_unavailable 处理,避免跨用户枚举。
  • 默认每个用户最多 20 个未撤销端点;已有端点重连不受上限影响,达到上限时拒绝登记新的机器标识,不自动淘汰旧端点。私有化部署可配置上限。
  • WebSocket Upgrade 后客户端必须在 5 秒内发送 hello,其中包含支持的整数协议主版本列表、机器标识和端点资料。服务端选择共同支持的最高版本并返回 welcome、服务时间、心跳参数和限制。
  • 没有共同协议版本时按协议错误关闭。新增可选字段可保持同一主版本,删除字段、改变字段含义或交互语义需要提升主版本。
  • hello 可以更新系统端点资料,但不能覆盖用户设置的别名。新连接完成鉴权和登记后原子替换相同用户、相同机器标识的旧连接。
  • 同一端点只保留一条有效连接。旧连接因替换关闭后不得自动重连,避免复制机器标识造成连接替换风暴。
  • 服务端在 welcome 后发送 directory.snapshot,并在同一用户任一端点上线、离线、资料变化、撤销或恢复时向所有在线端点重新发送完整快照。
  • 目录快照不包含 revision、增量补丁或删除事件;客户端必须整体替换本地端点数组。快照包含当前端点自身和全部未撤销端点,包括离线端点。
  • 每个 WebSocket 文本帧承载一个完整 UTF-8 JSON 对象。禁用二进制帧、permessage-deflate 和整段 JSON 的 Base64 包装。
  • 原始入站帧与服务端规范化并注入字段后的转发帧都不得超过 256 KiB。原始帧超限以关闭码 1009 断开;仅规范化后超限则返回 payload_too_large 并保留连接。
  • Agent 业务消息只有 eventrequestresponse 三类,全部为明确目标的单播。目录快照是系统消息,不属于业务广播。
  • 每条 Agent 消息由发送客户端生成 UUIDv4 message_ideventrequest 携带由 Agent 定义的方法名,方法名以小写字母开头,只允许小写字母、数字、点、下划线和连字符,最长 128 个字符。
  • payload 顶层必须是 JSON 对象;无参数使用空对象。桥接服务只校验信封,不维护方法目录,也不理解载荷语义。
  • response 使用新的消息标识,通过 reply_to 引用请求,不重复方法名。桥接服务为所有转发业务消息注入基于鉴权连接的可信 source 和毫秒级 routed_at
  • 客户端不得上报 sourcerouted_at;伪造服务端专属字段返回 invalid_message。未知信封顶层字段被丢弃,payload 内部字段原样保留。
  • 通用客户端库按请求消息标识维护 pending,默认超时 30 秒并允许 Agent 按方法覆盖。响应必须同时匹配仍在等待的引用、预期来源、当前目标、类型和合法且未处理过的响应消息标识。
  • 请求超时或连接中断时删除 pending 并返回本地 outcome_unknown。迟到、重复、未知引用或来源不匹配的响应被忽略,只允许记录不含载荷的元数据告警。
  • 桥接服务不维护业务请求状态,不发送成功送达确认。可在路由阶段确定的失败返回协议错误;Agent 是否收到、执行和成功只能由业务 response 表达。
  • 桥接服务和通用客户端库都不自动重试、不按消息标识去重、不保存离线消息。只有具体 Agent 确认方法幂等后才能自行重试并复用原消息标识,接收端负责去重或结果缓存。
  • 在双方连接连续期间,同一来源到同一目标的业务消息按发送顺序进入目标队列;不保证跨发送方、跨重连、请求响应或消息标识的全局顺序。
  • 协议错误至少覆盖无效消息、不支持版本、未鉴权、端点撤销、端点数超限、目标不可用、目标离线、目标繁忙、陈旧路由、限流、载荷过大和服务不可用。retryable 仅表达稍后重试可能成功,不授权自动重试业务请求。
  • 服务端每 30 秒发送 WebSocket 原生 Ping,10 秒内未收到对应 Pong 时关闭连接,不定义 JSON 心跳。每次心跳同时复验登录会话,会话失效时关闭连接。
  • 客户端根据关闭原因决定是否重连。网络中断、内部错误、服务重启和过载使用约 0.5 秒起步、最大 30 秒且带随机抖动的指数退避;稳定在线 60 秒后重置退避。
  • 正常关闭、协议不兼容、策略违规、帧超限、连接替换、端点撤销和会话失效不自动重连。重连后重新握手并用新快照替换目录,不重发断线前的 Agent 请求。
  • PostgreSQL 持久化端点目录、资料和撤销状态。Redis 保存用户、机器标识、实例、连接代次和 60 秒在线租约,各桥接实例只持有本地 WebSocket。
  • 新连接登记、旧连接替换、实例位置和连接代次写入必须原子完成。正常断开立即清理仍匹配当前代次的租约;实例异常退出后以租约过期判定离线并触发目录快照。
  • 同实例目标直接进入本地队列;跨实例目标通过实例级 Redis Pub/Sub 通道转发,并携带目标连接代次。目标实例只有在本地连接代次完全匹配时才投递,否则返回 stale_route,桥接层不自动重新查找和重试。
  • Redis 不可用时失败关闭:拒绝新桥接连接或返回 service_unavailable,不降级为仅本实例可见的在线状态。Pub/Sub 不承担持久化和补发,与仅在线路由语义一致。
  • 每条连接使用同时限制消息数量和字节数的有界发送队列。队列已满返回 target_busy,不阻塞实例、不静默丢弃;目标长期无法排空时关闭目标连接并更新在线状态。
  • 控制帧、协议错误、撤销通知和目录快照优先于业务消息,但调度器需避免业务消息永久饥饿,并保持同一来源到同一目标的业务 FIFO。
  • 同时按用户和发送端点限制单位时间消息数及载荷总字节数。首次超限返回 rate_limited 和可选重试建议,持续超限按策略违规关闭连接。
  • 带非空 Origin 的 WebSocket 请求必须匹配可信来源白名单;原生客户端允许省略 Origin,但仍必须通过 Cookie 会话鉴权。不得复用宽松跨域升级策略。
  • 首版只有 WSS 传输加密,不提供端到端加密。桥接服务可以解析信封并在内存中接触载荷字节,但不得解释业务语义或持久化业务载荷。
  • 日志、指标、协议错误和安全审计永不记录 payload 原文,只记录用户、来源与目标机器标识、消息标识、类型、方法、载荷大小、路由结果和延迟等元数据。
  • 文件始终保留在源端点本地,不上传 OSS 或桥接服务。其他端点通过 Agent 自定义协议传输文件内容;单文件暂限 5 MiB,每条文件消息仍遵守对象载荷与 256 KiB 帧上限。
  • 核心协议不定义任何固定文件方法,也不定义文件请求结构、分块、编码、偏移、完整性校验、路径权限或文件业务错误;这些全部由 Agent 自行约定。
  • 桥接实例优雅停机时停止接受新连接和业务消息,向现有连接发送服务重启关闭码,只删除属于本实例且代次匹配的租约,并在最多 10 秒内完成退出。

Testing Decisions

  • 采用一个最高层的后端端到端集成测试套件作为主要测试接缝,通过真实 HTTP 服务、真实 Cookie 会话鉴权和真实 WebSocket 客户端观察外部行为,不直接断言内部队列、锁、数据库查询或 Redis 键结构。
  • 复用现有 handler 路由测试的 HTTP 服务装配方式、现有 Cookie 鉴权中间件、内存数据库测试基建、内存 Redis 测试实例以及现有 WebSocket 客户端库;不为测试额外暴露生产内部接口。
  • 该套件启动两个桥接服务实例并共享数据库与 Redis,分别连接同一用户的桌面端和移动端,验证握手、协议版本协商、全量目录、跨实例双向 event / request / response 路由和严格响应关联。这是实现是否可交付的主路径测试。
  • 在同一套件中使用第二个用户验证发现域隔离:目录不可见、即使知道机器标识也只能得到目标不可用,团队或管理员身份不能绕过用户边界。
  • 验证机器标识首次登记、已有端点资料更新、别名不被 hello 覆盖、端点上限,以及查询、改名、撤销和恢复管理接口的外部行为。
  • 验证每次上线、离线、资料变化、撤销和恢复均广播新的完整目录;客户端用新快照即可重建正确状态,不需要 revision 或历史增量。
  • 验证相同机器标识的新连接替换旧连接、旧连接收到正确关闭原因且不会继续收到消息,旧连接清理不能删除新连接租约。
  • 验证请求响应关联只接受预期来源和仍在等待的 reply_to,并覆盖重复响应、迟到响应、未知引用、来源不匹配、断线和默认超时后的 outcome_unknown
  • 验证目标离线、不可见、队列已满、连接代次陈旧、限流、Redis 不可用和规范化后超限返回对应协议错误,并且不会出现成功送达确认或自动重试。
  • 验证原始文本帧超过 256 KiB 使用关闭码 1009,二进制帧、无效 JSON、非法方法名、非对象载荷和伪造服务端字段被拒绝,业务载荷不会出现在测试捕获的日志与错误中。
  • 验证同一来源到同一目标在连续连接期间保持 FIFO,但测试不假设跨来源、跨重连或响应顺序。
  • 验证原生 Ping/Pong、心跳会话复验、60 秒租约过期、实例异常退出、正常断开、滚动重启和客户端关闭码策略。时间相关场景使用可控时钟或现有 Redis 时间推进能力,避免真实等待。
  • 验证带不可信非空 Origin 的连接被拒绝,可信来源和省略 Origin 的原生客户端在 Cookie 有效时可以连接。
  • 文件传输只测试核心边界:桥接服务不创建持久化文件或 OSS 对象、文件消息仍按普通 Agent 消息路由、单帧限制继续生效。具体文件方法、分块、编码和大于 5 MiB 的 Agent 业务错误不在桥接服务测试中固定。
  • 保留少量客户端连接状态机测试,覆盖全量快照替换、pending 生命周期、严格响应匹配、断线不重发、关闭码分类和带抖动退避;这些测试只断言客户端可见状态和发出的协议消息。
  • 所有测试都以协议可观察行为为准;内部存储、实例协调和队列实现可以重构,只要相同外部场景仍通过。

Out of Scope

  • 纯浏览器作为端点,以及依赖页面 JavaScript 直接管理机器标识或原生 Ping/Pong。
  • 跨用户端点发现和通信,以及配对码、临时分享、团队、项目或管理员授权继承。
  • 一个端点注册多个 Agent、Agent 能力目录、服务端理解任务、会话、工具调用或任务接续模型。
  • 端到端加密、端点密钥、配对确认、密钥轮换、丢失恢复和多端密钥同步。
  • 离线消息、存储转发、消息补发、成功送达回执、桥接层自动重试、桥接层去重和恰好一次执行。
  • 业务广播、全局顺序、跨重连顺序和服务端维护业务请求状态。
  • WebSocket 二进制帧、消息压缩、超过 5 MiB 的文件,以及将文件上传 OSS 或持久化到桥接服务。
  • 固定的文件读取方法、文件请求模型、分块、编码、校验、路径权限和文件业务错误。
  • 彻底删除端点记录,以及把端点撤销当作失窃设备会话处置方案。
  • 立即迁移或替换现有任务流、任务控制、终端及其他已有 WebSocket。

Further Notes

  • “端点”是可发现、可寻址的原生应用安装实例;“Agent”是通过端点参与通信的执行主体,两者共享一对一身份。任务是 Agent 管理的资源,不是端点。
  • 机器标识用于稳定寻址,不具有认证能力。真正的安全边界是当前登录会话与同一用户发现域。
  • 请求超时或断线后的 outcome_unknown 是协议的重要语义:它明确表示无法判断目标是否已经执行,调用方不能把它降格为普通失败并盲目重试。
  • 桥接服务只承诺在当前在线连接间尝试路由。即便消息已经写入目标连接,也不代表目标 Agent 已接收、处理或成功执行。
  • 5 MiB 是单文件业务上限,不改变 256 KiB 单消息帧上限。如何把文件映射到多条 Agent 消息完全由 Agent 协议决定。
  • 首版上线应与现有任务通信链路并存;后续任务接续可作为 Agent 自定义方法逐步迁移到桥接通道,而无需改变桥接核心协议。

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the existing handler route tests, Cookie authentication middleware, WebSocket client library, and HTTP service assembly described in the issue. Trace how the new endpoint HTTP and WebSocket behavior should coexist with existing task and terminal channels. Done means the documented end-to-end scenarios pass across two service instances, including discovery, routing, isolation, lifecycle, limits, and failure handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
electron, postgresql, react-native, redis, typescript
Domain
api, backend, databases, distributed-systems, security, testing
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
25/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.