# 星线开放平台技术概览

开放平台管理第三方应用、OIDC 登录授权、服务端签名 API 和 Webhook，实现与[星线账户](https://document.thestarline.cn/account/)同在 `identity/`，使用账户身份与 MySQL 存储，通过 `https://open.thestarline.cn` 提供独立平台界面。资料依据 2026 年 10 月 23 日源码整理；外部应用接入资格与生产回调需单独验收。

## 三种接入凭据

| 能力 | 使用的证明 | 适用范围 |
| --- | --- | --- |
| OIDC 授权码 | `clientId`、PKCE，机密客户端另用 `clientSecret` | 用户主动登录并同意声明范围 |
| 签名开放 API | `clientId` 与独立 `apiSecret` 的 HMAC | 受控服务端调用，不使用账户 Cookie |
| Webhook | 独立 `webhookSecret` | 接收账户或应用状态事件 |

三类密钥不能互换。公开客户端不保存机密客户端密钥；API 密钥、Webhook 密钥只配置在接入方服务端。创建应用、启用 API 和配置通知目前属于平台管理员操作，不是任何登录用户均可调用的公开自助注册 API。平台管理权限也不由 OIDC 返回的普通用户身份自动授予。

## 应用模型与注册约束

`identity/server/protocols.ts` 的应用模型包含内部 `id`、对外 `clientId`、名称、类型、精确回调列表、允许声明范围、启用状态，以及 API 与通知的独立开关。应用创建时可返回机密客户端的原始密钥，列表接口不返回密钥。密钥在平台数据库中使用服务端保护机制封装；接入方应在创建响应时安全接收并托管。

应用名称上限 120 个字符串长度单位，类型为 `public` 或 `confidential`，回调 1–10 项，权限必须包含 `openid`。可登记 `email`、`profile`、`phone`、`verification`、`management`。回调校验要求规范化后完全相同的 HTTPS URL，无用户信息、片段或通配符；公开客户端的本地开发才可使用带有效端口的本机回环 HTTP。自定义原生 scheme 不能直接登记为此处 OIDC 回调。

应用停用会撤销关联授权状态，并可能发出状态通知。接入方不应因为缓存了一次 clientId、旧授权或成功截图，就假定后续调用仍被允许。应用启用、API 启用、用户有效授权三者是不同判断。

## OIDC 授权与声明

协议实现位于 `identity/server/oidc.ts`，发行者为 `https://account.thestarline.cn/oidc`。发现文档位于该发行者下的 `/.well-known/openid-configuration`。接入端从发现文档读取授权、令牌、UserInfo 与 JWKS 地址，不把账户站网页路由当作协议端点。

当前只启用 `code` 响应类型，所有客户端均要求 PKCE。客户端认证方式为公开客户端 `none` 或机密客户端 `client_secret_basic`。授权码有效期 60 秒；Access Token 和 ID Token 各 900 秒；Grant、协议 Session 各 3,600 秒，交互 300 秒。账户网页登录的 8 小时 Cookie 会话不等于这些协议对象的期限，也不能据此延长访问令牌。

| scope | 可能提供的声明 | 限制 |
| --- | --- | --- |
| `openid` | `sub` | Account 的稳定用户主键 |
| `profile` | `name` | 优先显示名称，可能回落到邮箱名称部分 |
| `email` | `email,email_verified` | 账户确有邮箱时提供 |
| `phone` | `phone_number,phone_number_verified` | 账户确有手机号时提供 |
| `verification` | 认证摘要 | 不包含个人证件材料；企业名称限获批企业 |
| `management` | 管理状态摘要 | 不替代业务系统自己的角色校验 |

最终声明取决于应用登记、实际请求、用户同意和账户资料，不是 scope 名出现就必有非空字段。凭据版本变化、会话撤销、应用停用和封禁检查会影响授权有效性。接入方应验证签名、issuer、audience、nonce 和时间，并使用 `sub` 关联本地用户。

## 签名 API 的数据边界

当前业务路由只有 `POST /api/open/v1/ping` 与 `GET /api/open/v1/users/:id`，不包含批量用户导出、任意资料写入或第三方直接改密。查询用户要求 `users.read`；邮箱、手机号还分别要求 `users.email`、`users.phone`，同时受该用户对该应用 OIDC 同意范围约束。

用户查询还要求存在当前有效的授权门禁和关联 Account 会话，且其凭据版本与账户一致。没有满足条件的授权返回 404，以统一表达“不存在或无权访问”；不能用平台管理员看得到某用户来替代接入应用的用户授权。响应邮箱、电话字段可能省略，接入方应按可选字段解析。

应用配置、用户同意、协议对象和防重放记录分别持久化。删除接入方本地 Cookie 不会主动删除平台应用；停用应用也不等于删除账户。接入方应把本地登录会话、平台授权状态和通知处理记录分开维护，避免把某一层的状态变化误判为其他层已经完成退出或清除。

签名包含请求方法、原始路径与查询串、秒级时间戳、nonce 和原始正文。允许时间偏差 300 秒，nonce 以应用为范围去重。服务端先做来源限额，再核验签名，最后应用级限额；API 请求体最多 16,384 字节。签名细则与例子见[接入与协议细则](https://document.thestarline.cn/open-platform/integration.md)。

## 通知、密钥轮换与运行要求

Webhook 可以发送 `user.banned`、`application.disabled`、`user.closed`、`ping` 等事件，正文含随机事件 `id`、毫秒 `createdAt`、`appId` 和 `data`。请求用独立密钥签名。当前发送实现记录投递结果并返回成功布尔值，没有可据此宣称的持久化重试队列或保证送达机制；接收方应保持自身业务状态可回读、事件幂等和失败监控。

API 密钥轮换给旧密钥 5 分钟重叠期，禁用会清除当前与旧 API 密钥。Webhook 轮换立即更换，不提供同样的旧密钥宽限。通知 URL 在生产需 HTTPS，禁止私网或保留目标、用户密码、片段与通配符；解析结果被固定到实际连接，不跟随重定向。发送超时 5 秒，响应消费有字节上限。

生产依赖 Account 的数据库、PII 和主保护密钥、稳定 OIDC JWKS、精确站点来源及可信代理配置。不要因切换开放平台域名而重建身份库或签名密钥。`identity/tests/open-api.test.ts`、`oidc-profile.test.ts`、`oidc-redirect.test.ts` 验证部分协议契约；真实第三方回调、轮换交接、通知接收与停用传播需要单独联调。
