跳转至

Gerege Kiosk

Production · 第 4 层 — 垂直产品 · 仓库:gerege-kiosk-mn · geregekiosk.mn

自助服务终端的统一平台——以 eID 为基础、由 AI 增强。 它把设在公共场所的 终端与电子身份证件连通,让公民无需排队、无需见办事人员即可领取证明、缴纳费用、 打印凭据。不受办公时间限制,24 小时可用。

归属

平台由 Gerege Kiosk ХХК 拥有并运营。源代码位于私有仓库中, 构建在 Gerege Systems 共用的 open-gerege-core 底座之上。

geregekiosk.mn 现在提供的是 Gerege Nexus

2026-08-07 核查:https://geregekiosk.mn/ 返回的是 Gerege Nexus 的部署——页面标题为「Gerege Nexus」,描述也是 Nexus 的。 该域名有自己的有效证书,主机为 38.180.243.183

因此本页所述的 gerege-kiosk-mn 行为可能已与公开域名实际提供的内容不符。 请以该部署为准核对终端上运行的版本。

核心思路——瘦应用、厚底座

Kiosk 的 Go 后端只有一个文件。认证、RBAC、API 网关、AI 流水线、eID/SSO ——所有底层能力都位于 github.com/gerege-systems/open-gerege-core 模块中; 本仓库按版本拉取它,并以自己的名义启动:

func main() {
    server.ServiceName = "gerege-kiosk"

    app, err := server.NewApp()
    if err != nil { /* … */ }

    // 应用自己的路由在此添加:
    //   app.Router().Route("/api/xxx", xxx.Routes(app.Pool()))

    if err := app.Run(); err != nil { /* … */ }
}

这正是 Template Platform 页面所提到的 fork 同步技术债的解法: 过去底座代码会复制到每个仓库,每项改进都得手工搬运。如今 Kiosk 是 open-gerege-core版本化消费者——安全补丁自单点扩散,更新只需一条 go get open-gerege-core@latest

位于何处 归谁所有
底座后端(认证、RBAC、AI、网关、迁移) open-gerege-core 模块 Gerege Systems
启动入口、品牌、配置 gerege-kiosk-mn/backend Gerege Kiosk ХХК
前端 BFF、UI gerege-kiosk-mn/frontend Gerege Kiosk ХХК
部署、edge vhost gerege-kiosk-mn/deploy Gerege Kiosk ХХК

组成结构

gerege-kiosk-mn/
├── backend/     # Go · open-gerege-core 的瘦消费者(cmd/api/main.go)
├── frontend/    # Next.js 15 BFF —— Node 20、TanStack Query、mn/en/zh/ru
├── ios/         # SwiftUI 参考客户端(只经 BFF 通信)
└── deploy/      # compose、edge nginx vhost、内部数据库的 TLS 证书

底座后端遵循 Clean Architecture——handler → usecase → repository → domain, 无反向引用,且不使用 ORM(基于 pgx 手写 SQL)。

认证——只用 Gerege SSO

登录页上只有一个按钮:用 Gerege SSO 登录没有密码、没有邮箱/OTP 注册,也没有直连的 eID 流程。

graph LR
    C["公民 / 终端"] --> W["geregekiosk.mn<br/>Next.js BFF"]
    W --> A["Kiosk API"]
    A --> S["sso.gerege.mn<br/>Gerege SSO"]
    S --> E["eID Mongolia"]
    S -.->|"eID 代理"| A
  • OIDC RP 流程——/api/auth/sso/startsso.gerege.mn/sso/callback。 移动端另设带 PKCE 的公开客户端(native)流程。
  • 会话——JWT access + refresh,refresh 会轮换;登出会作废 refresh, 并把 access 加入拒绝名单。
  • 令牌不会进入浏览器——只存在于 httpOnly cookie 中,一切经由 BFF。

为什么 Kiosk 自己不做 eID RP?

按生态系统边界规则第 2 条,第 3–4 层的应用 不得直接访问 eID。Kiosk 不持有 eID RP 凭据——与 eID 的一切往来都经 Gerege SSO。这样凭据集中于一处,审计链路也不会中断。

eID PKI 档案——经由代理

已登录公民的 PKI 面板通过 SSO 的 eID 代理获取。Kiosk 用用户的 access token 发起调用,由 SSO 以自己的 eID 凭据取回数据。

内容 展示位置
汇总概览 /me/eid/id
证书与状态 /me/eid/certificates
已关联设备 /me/eid/devices
认证/签名历史 /me/eid/logs
关联机构与法定签署人 /me/organizations

代理被关闭(SSO 上 eid-proxy 服务未启用)或令牌失效的情形由 UI 单独处理 ——不会一概抛出 5xx。

自身也是 OIDC 提供方

Kiosk 在作为 SSO 依赖方的同时,也能充当身份提供方。配置了 OAUTH_ISSUER 与 state key 之后,其自研的 Go OAuth2/OIDC 提供方即启用(不使用 Ory Hydra):

  • /oauth 下的 login · consent · logout 页面;
  • oauth_clients 表中登记 RP,并支持 secret 轮换;
  • 对第一方 client 跳过授权同意,并记住同意结果;
  • discovery、userinfoid_token——签名密钥以加密形式保存。

由此,Kiosk 周边的小型应用便可提供「Sign in with Gerege Kiosk」

面向公民的界面

板块 作用
/me/dashboard 个人面板
/me/services · /me/applications 服务目录、申请及其进度
/me/references 各类证明
/me/notifications 通知
/me/payments 缴费
/me/appointments 预约
/me/organizations 机构、成员关系、权限
/me/eid/sign 为文件加盖电子签名
/me/integrations 第三方连接与 Gerege Space
/me/ai · /me/translate AI 助手、实时翻译

创建/检索机构时,会经 Gerege Verify 向国家登记查询。机构数据按用户 以 Postgres RLS 加以保护。

统一的服务登记

Ring System 的 R1 组件——服务护照与证明材料管理:

  • 服务目录、版本、发布/归档;
  • 人生事件(life events)——按公民的处境对服务进行归类;
  • 证明材料(evidences)与 once-only 面板——衡量「不再索取已提交过的 材料」这一原则的落实程度。

权限分两级:registry.view(读)与 registry.manage(写)。

API 网关

由管理端维护的服务目录:services · routes · consumers · API key · policy, 另有请求遥测(overview + logs)。

当前覆盖范围

网关目前是管理与遥测层。把已配置的 route/policy 作为真正的反向代理 强制执行(在 consumer 级别做限流与配额)的工作尚在计划中。

电子签名与 sign relay

  • PAdES——通过 eID Mongolia 的 /v3 接口在服务端为 PDF 签名;配有长期的 Document-Signer 证书(生产环境为 fail-closed)。
  • Sign relay——让第三方 RP 借助平台的 eID 凭据完成签署的通道。该路由 不走 web BFF,而是从 edge 直连 API(loopback 端口)。结果通过 webhook 通知。

公民以 PIN2 作出的个人签名与系统 Document-Signer 签名之间的区别,请见 G-Sign 页面。

AI 助手(Gemini)

基于无 SDK 的 REST 客户端构建的流水线:

能力 说明
聊天 文本与语音消息、function calling
STT 语音 → 文本
TTS 文本 → 语音(PCM→WAV)
翻译 实时流式翻译

三层 system prompt:代码中硬编码的护栏,加上管理员通过数据库配置的适用 范围与指令。护栏层永不可配置

search_knowledge 工具让回答立足于知识库中的真实数据。检索是语义的 ——Gemini embedding + pgvector 余弦近似,失败时回退到 ILIKE。

Gemini 短暂故障时,聊天不会变成 5xx,而是返回用户语言的降级回复degraded: true)。/ai/* 路由按 IP 限制约每分钟 20 次请求。

集成与存储

  • 第三方 OAuth 连接——Google Drive · Google Meet · Dropbox。令牌以 AES-256-GCM 加密存储;若未配置凭据,相应卡片会以「即将推出」状态显示为 不可用。
  • Gerege Space——应用自带的 SFTP 存储,按用户设有配额。会校验 SFTP host key(生产环境必须校验,否则 fail-closed)。

权限、管理与审计

  • RBAC——动态角色 + 权限目录,四级模型 (superadmin → admin → manager → user)。
  • 超级管理员——独立账户,带 MFA 的 onboarding 流程(邀请白名单 → Google → eID → 邮箱 OTP → TOTP + 恢复码)。因保存在单独的表中,同一个人既可以是 eID 管理员,也可以是超级管理员。
  • 审计日志——哈希链式、仅追加;管理员可读,并提供完整性校验 endpoint。
  • 安全事件——事件接入与监控面板。
  • 站点外观——由管理员配置的强调色 / 字体 / 密度 / 主题,并支持按用户覆盖。

安全

控制项 实现方式
数据隔离 Postgres RLS(ENABLE + FORCE);api 以 superuser 角色连接,并在启动时校验其确已生效
会话 httpOnly cookie,令牌绝不进入客户端 JS
CSRF 双重防护——自定义请求头 + origin 校验(BFF 的所有写操作路由)
响应头 CSP · HSTS · COOP/COEP/CORP,CORS 白名单
限流 登录约每分钟 5 次(请求体上限 4 KiB),应用 50 r/s,/ai/* 约每分钟 20 次
数据库连接 生产环境为 sslmode=verify-full——使用内部 CA 的 TLS
观测类 endpoint 生产环境中 /metrics/swagger 由 bearer token 保护
代理信任 未设置 TRUSTED_PROXIES不信任 X-Forwarded-For(防止伪造限流/审计信息)

生态系统的通用要求请见安全页面。

可观测性

OpenTelemetry 链路追踪 + Prometheus 指标 + Zap 结构化日志。在遥测中该服务以 gerege-kiosk 之名出现。

部署

Docker Compose 栈:db(Postgres 16 + pgvector) · redis · migrate (一次性) · api · web。浏览器只能触达 web;api/db/redis 留在内部网络, 不开放公网端口。

部署方面有三项决策值得留意:

  1. 迁移是独立步骤,而不是 up -d 的一部分。此前每次重跑 migrate 都会重建 api 与 web,即便是没有改动代码的 commit 也会带来一秒钟的 502。
  2. 若一切未变,则完全不动。 Docker 构建并非可复现,同一份代码也会产出新的 image ID。因此 HEAD 未变时,整个部署直接跳过。
  3. 数据类服务不在每次部署时构建——重建 db 会切断所有活动的数据库连接。

edge nginx 的 vhost 由本仓库自己持有——每次部署都安装到 conf.d,经 nginx -t 校验后 reload;校验失败则回退到先前的配置。这与 docs.gerege.mn、Developer Portal、 Template Platform 采用的是同一模型

语言

界面与文档提供四种语言:Монгол · English · 中文 · Русский。前端词条的 完备性由测试强制保证——某个键在任一语言中缺失,CI 就会失败。

当前状态

Production 已在 geregekiosk.mn 上运行。底座平台的能力已完整继承; 终端业务特有的流程仍在持续补充。

后续步骤:网关的实际强制执行、聊天的流式(SSE)响应、基于 nonce 的 CSP、 数据库自动备份与恢复演练、staging 环境。

相关页面