# 星企技术概览

星企是独立的企业协作客户端，拥有 iOS、Android 工程，与[星线 App](https://document.thestarline.cn/app/)共享聊天服务的账户映射与部分基础设施。企业 API 位于 `chat-service/src/enterprise-routes.mjs`，并不因此成为星线 App 的前台功能。资料依据 2026 年 10 月 23 日源码整理；两端界面仍标记开发预览，正式企业服务及商店发布不能由源码或本机样例推定。

## 工程与服务边界

iOS 工程在 `xingqi-ios-app/`，使用 Swift、SwiftUI、URLSession 与独立安全凭据存储；Android 工程在 `xingqi-android-app/`，使用 Kotlin、Compose。二者 application/bundle 标识为 `cn.thestarline.xingqi`，与个人聊天产品分离。iOS 当前面向 iOS 17 及以后，Android 最低 API 26，编译与目标 API 35；构建元数据仍需随发布重新核对。

共享服务把 Account OIDC 用户映射为聊天用户，再使用聊天 Bearer 会话访问企业路由。Account 用户主键、聊天用户 UUID、组织 UUID 和消息序号各自独立。企业角色存储在企业成员关系中，与 Account 的平台管理员角色不相互授予。

| 模块 | 当前数据与操作 | 服务端实现 |
| --- | --- | --- |
| 企业空间 | 创建、列出、选择组织，读取聚合工作区 | `enterprise/organizations.mjs` |
| 通讯录 | 部门、成员角色、职务、企业名片 | `enterprise/core.mjs`、`organizations.mjs` |
| 邀请与入企 | 有效期邀请码、预览、申请、审批、记录 | `enterprise/admissions.mjs` |
| 企业会话 | 全员群、同事单聊、成员群、文本、未读 | `enterprise/channels.mjs` |
| 工作内容 | 待办、公告与已读、HTTPS 办公服务入口 | `enterprise/content.mjs` |
| 数据约束 | 企业外键、成员关联、消息去重与历史边界 | `enterprise/schema.mjs`、`content-schema.mjs` |

以上路径均相对 `chat-service/src/`。当前未提供企业附件上传、音视频会议、考勤、网盘、企业认证审批或端到端加密主链路；不能把个人 App 的其他接口、占位页面或企业认证“待开放”界面写成已实现企业能力。

## 企业、成员与权限

创建组织时，服务端在同一事务创建组织、owner 成员和唯一 general 全员群。成员角色为 owner、admin、member。owner 可以给非所有者设置 admin/member；admin 不能提升自己、改所有者角色或移除其他管理员；所有者不能通过普通移除接口删除。部门、成员和服务均限定当前组织，不能只凭一个有效对象 ID 跨企业操作。

本人名片 PATCH 只接受 `name`，名称为 1–80 个 Unicode 字符的单行文字，null 恢复为账户名称。企业通讯录同时返回 accountName、cardName 与解析后的 displayName。名片是组织内资料，不修改 Account 全局名称，也不把一个企业的昵称带到另一个企业。管理者修改成员时还可维护部门、职务和受权限限制的角色。

邀请由管理者创建，随机码有效期 3 天，数据库只存摘要；它可以被多位同事使用，但仍需要管理者审批。预览只确认企业、期限和本人状态，不直接加入。申请人不能审批自己的申请，已决定的申请不能改为相反结果。重新申请需要新的有效邀请，不能复活已处理的旧记录。

## 会话与可见历史

会话类型为 general、direct、group。创建同事单聊要求最终恰好两名当前企业成员，同一对成员以稳定键复用会话。群会话也只能选择当前企业成员；企业成员资格并不自动提供某个专用群的访问权限，还要检查频道成员关系。

成员加入频道时保存 `visible_after` 历史边界和 `last_read`。新入企成员进入全员群只能看到加入边界后的消息；移除成员会通过外键清理其频道资格，重新加入时不会据此重新获得早期历史。消息列表最多 100 条，通过 `before` 向前翻页，按时间序号升序返回本页；消息 ID 是 JSON 字符串，客户端不应按字典序比较。

发送仅接受文本 `body` 与 `clientId`。服务端以频道、发送者、clientId 去重；同一内容重试返回原消息，换正文却复用 ID 返回冲突。未读计数排除本人发送的消息，并受个人可见边界与已读位置限制。企业消息没有单独事件游标或 WebSocket 推送接口，两端通过轮询更新工作区和当前会话。

## 待办、公告与办公入口

任意成员可以创建待办，指派对象必须是当前企业成员。管理者和创建者可以修改完整内容或删除；仅作为被指派人的普通成员只能更新完成状态。标题最多 120 字符，备注 4,000 字符，dueAt 是可空的安全整数毫秒时间，isCompleted 是布尔值。

公告由管理者发布、删除，所有企业成员可以标记已读。已读关系去重，重复打开不增加人数。标题最多 120 字符、正文 10,000 字符。服务入口由管理者维护，名称最多 80 字符、URL 最多 2,000 字符，只接受不嵌入账号密码的 HTTPS 地址，并拒绝控制字符等危险表达。

iOS 办公服务在非持久化网站数据容器中打开，Android 使用外部系统浏览器；不会把企业 Bearer 令牌注入外部网站。服务卡片是网址入口，不代表星企代理了该网站的认证、数据、审批或可用性。

## 客户端隔离与验收边界

两端使用会话与企业选择代次隔离异步响应，切换账号或企业时清除工作区、频道、草稿和待处理动作，避免旧请求覆盖新企业。401 需要处理账户会话；403 可能只是成员或管理权限变化，通常重新读取组织与当前角色，不能把它一律等同于 Account 全局退出。

当前星企登录仍从 `GET /auth/start?app=xingqi` 进入浏览器，回到 `xingqiworkbench://auth` 后只以 ticket 换票。聊天服务到 Account 的 OIDC 有 PKCE，但两端没有采用星线 App 已有的 `/auth/native/start` 原生附加 proof；不能宣称二者登录实现完全一致。

仓库有 iOS 契约、消息排序、企业隔离、退出持久化及 UI 测试，Android 有领域与企业流程等测试，服务端另有企业模块测试。本机专用样例入口仅用于隔离预览，生产 `/__preview/enterprise/session` 明确返回 404。历史测试记录不构成真实 Account 登录、跨网络企业业务或商店审核通过。具体接口与联调方法见[星企接入细则](https://document.thestarline.cn/xingqi/integration.md)。
