10 — 应用目录(生态一键登录 / App Directory)
🚧 状态:后端只读端点 + 数据模型已实现;前端展示分阶段接入。 让用户在注册/登录时 看到「拥有一个鲲 Galgame 账号,即可一键登录以下网站」——按 OAuth client 的开关(opt-in) 列出生态内的站点。本文是下游(kungal / moyu / wiki)展示这条「生态 strip」的跨服务契约。
这对应业界成熟的 App Launcher / app directory 模式(Salesforce、Cloudflare Access、 Microsoft 365 的「九宫格」),各家都是私有实现 + 每个 app 一个可见性开关——OAuth/OIDC 没有公开列举 client 的标准,所以这是产品元数据,不是协议缺口。本文的形态是「注册/登录 页的生态价值展示」,数据与 App Launcher 同源。
1. 模型:每个 OAuth client 一个 opt-in 开关
oauth_clients 新增(管理员在 OAuth 后台「OAuth 客户端」里配置):
| 字段 | 含义 |
|---|---|
listed (bool, 默认 false) |
是否出现在公开应用目录里。opt-in——内部/管理类 client 默认不出现 |
logo_url (string) |
站点 logo(strip / tile 用) |
tagline (string) |
一句话简介,如「Galgame 论坛」 |
display_order (int, 默认 0) |
排序(小在前,再按 name) |
列表内容 = 所有
listed=true的 client。复用已有的name与其所属 Site 的domain。
2. 端点:GET /api/v1/oauth/ecosystem(公开,可缓存)
无需鉴权——这是公开营销元数据,只暴露展示字段,不含 secret / redirect_uris / scope / 配额。建议前端缓存(内容很少变)。
响应(data):
{
"apps": [
{ "name": "鲲Galgame论坛", "site_domain": "www.kungal.com", "logo_url": "https://…", "tagline": "Galgame 论坛", "auto_consent": true },
{ "name": "摸鱼galgame", "site_domain": "moyu.moe", "logo_url": "https://…", "tagline": "Galgame 补丁站", "auto_consent": true }
]
}
只返回 listed=true 的 client;排序 = 官方(auto_consent=true)在前,再 display_order,再 name。auto_consent 复用已有的第一方标志(见 doc 05):true = 第一方「官方」站点,下游据此展示「官方」标识并排在前面。
3. 下游接入(展示「生态 strip」)
同一个端点,三处复用:
- OAuth 注册页(
oauth.kungal.com自身,apps/web):注册卡片下方一条 logo strip—— 「拥有鲲 Galgame 账号,一键登录以下网站」。同源,直接调用。 - OAuth 授权页(某个 client 的登录流程中):高亮当前正在登录的 client,其余列为 「也可用此账号登录:…」,把同意/登录这一刻变成价值展示。
- 下游登录/注册 modal(kungal / moyu / wiki):
fetch https://oauth.kungal.com/api/v1/oauth/ecosystem渲染同样的 strip。
CORS(下游跨域读取必看):该端点是公开 GET,但下游浏览器跨域 fetch 时,消费方的
origin 必须在 OP 的 CORS 白名单内(internal/middleware/cors.go:目前含 kungal.com、
moyu.moe + 开发 origin)。接入子域(www.kungal.com / wiki.kungal.com)时需把其 origin
加进白名单,否则被 CORS 拦截。
UX 建议:logo + 名称、官方站点(auto_consent)显示 primary「官方」chip 并排在前、缓存
端点;纯展示,不触碰认证流。参考实现:apps/web 注册页(折叠为一排圆形 icon + 点击展开列表)、
moyu 登录 modal。
4. 安全 / 隐私
- 端点只返回 opt-in client 的公开展示字段——无 secret / 内部布局,可安全公开 + 缓存。
listed默认false(fail-closed):内部 / 管理 client 不会意外出现在公开目录。- 不在认证路径上:纯只读元数据,不改 token / session / 重定向,安全面几乎为零。
5. 实施阶段
- ✅ 后端:
oauth_clients加listed/logo_url/tagline/display_order+GET /oauth/ecosystem(公开、按序)。(DB 迁移kun_galgame_infra:cmd/migrate) - 🚧 OAuth 后台:客户端创建/编辑表单加这四个字段(管理员配置)。
- 🚧 OAuth 注册页 strip + 授权页「当前 client 高亮」。
- 🚧 下游 kungal / moyu / wiki 登录/注册 modal 接入 strip(+ 按需扩 CORS 白名单)。
- ⏳(可选)登录后的 App Launcher(账号中心九宫格)——同源数据,后续可叠加。
变更摘要
2026-06-25(设计 + 后端):新增本文。生态「一键登录」应用目录:
oauth_clients加 opt-inlisted+logo_url/tagline/display_order;公开只读GET /oauth/ecosystem返回listedclient 的展示字段。前端 strip(OAuth 注册/授权页 + 下游 modal)分阶段接入。 对应业界 App Launcher 模式(无 OAuth 标准,属产品元数据)。
源:kun-galgame-infra/docs/integration/oauth/10-app-directory.md